home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / oleo-1_4.lha / oleo-1.4 / ref.c < prev    next >
C/C++ Source or Header  |  1993-05-13  |  70KB  |  3,009 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <sys/types.h>
  23. #include <signal.h>
  24. #include "sysdef.h"
  25. #include "global.h"
  26. #include "cell.h"
  27. #include "eval.h"
  28. #include "io-abstract.h"
  29. #include "io-generic.h"
  30. #include "hash.h"
  31. #include "byte-compile.h"
  32. #include "parse.h"
  33. #include "ref.h"
  34. #include "cmd.h"
  35.  
  36.  
  37. #ifdef __STDC__
  38. static void add_ref_fm (struct ref_fm **, CELLREF, CELLREF);
  39. static void flush_ref_fm (struct ref_fm **, CELLREF, CELLREF);
  40. static void flush_range_ref (struct rng *, CELLREF, CELLREF);
  41. extern void shift_formula (int r, int c, int dn, int ov);
  42. #ifdef SPLIT_REFS
  43. /* These two are tunable paramaters */
  44. #define REF_START    3
  45. #define REF_INC        *=2
  46. #else
  47. static void flush_ref_to (struct ref_to **);
  48. static void flush_fm_ref (struct ref_fm *);
  49. #endif /* SPLIT_REFS */
  50.  
  51. #else /* !__STDC__ */
  52.  
  53. static void add_ref_fm ();
  54. static void flush_ref_fm ();
  55. static void flush_range_ref ();
  56. extern void shift_formula ();
  57.  
  58. #ifdef SPLIT_REFS
  59. /* These two are tunable paramaters */
  60. #define REF_START    3
  61. #define REF_INC        *=2
  62. #else
  63. static void flush_ref_to ();
  64. static void flush_fm_ref ();
  65. #endif /* SPLIT_REFS */
  66. #endif /* __STDC__ */
  67.  
  68. /* More tunable paramaters */
  69.  
  70. #define FIFO_START    40
  71. #define FIFO_INC    *=2
  72.  
  73. #define TO_MAGIC(row,col)    (((long)(row)<<BITS_PER_CELLREF)|(col))
  74. #define MAGIC_ROW(magic)    (((magic)>>BITS_PER_CELLREF)&CELLREF_MASK)
  75. #define MAGIC_COL(magic)    ((magic)&CELLREF_MASK)
  76.  
  77. #define BETWEEN(mid,lo,hi)    ((mid>=lo)&&(mid<=hi))
  78.  
  79. static VOIDSTAR moving;
  80.  
  81. int timer_active = 0;
  82. struct ref_fm *timer_cells;
  83.  
  84. CELL *my_cell;
  85.  
  86. #ifdef TEST
  87. extern int debug;
  88. #endif
  89.  
  90. /* Functions for dealing exclusively with variables */
  91. struct hash_control *the_vars;
  92.  
  93. struct value
  94.   {
  95.     int type;
  96.     union vals c_z;
  97.   };
  98.  
  99. /* For the fifo-buffer */
  100. struct pos
  101.   {
  102.     CELLREF row;
  103.     CELLREF col;
  104.   };
  105.  
  106. struct cell_buf
  107.   {
  108.     unsigned int size;
  109.     struct pos *buf;
  110.     struct pos *push_to_here;
  111.     struct pos *pop_frm_here;
  112.   };
  113.  
  114.  
  115. /* Set the cell ROW,COL to STRING, parsing string as needed */
  116. #ifdef __STDC__
  117. void
  118. set_cell (CELLREF row, CELLREF col, char *string)
  119. #else
  120. void
  121. set_cell (row, col, string)
  122.      CELLREF row;
  123.      CELLREF col;
  124.      char *string;
  125. #endif
  126. {
  127.   unsigned char *ret;
  128.  
  129.   cur_row = row;
  130.   cur_col = col;
  131.  
  132. #ifdef TEST
  133.   if (!string)
  134.     {
  135.       io_error_msg ("Null string to set_cell %s", cell_name (row, col));
  136.       return;
  137.     }
  138. #endif
  139.   while (*string == ' ')
  140.     string++;
  141.  
  142.   if (!*string)
  143.     {
  144.       my_cell = find_cell (cur_row, cur_col);
  145.       if (!my_cell)
  146.     return;
  147.       flush_old_value ();
  148.       return;
  149.     }
  150.  
  151.   my_cell = find_or_make_cell (cur_row, cur_col);
  152.   flush_old_value ();
  153.  
  154.   ret = parse_and_compile (string);
  155.   my_cell->cell_formula = ret;
  156. }
  157.  
  158. extern int default_lock;
  159.  
  160. /* new_value() calls set_cell, but refuses to change locked cells, and
  161.    updates and prints the results.  It returns an error msg on error. . .
  162.  */
  163. #ifdef __STDC__
  164. char *
  165. new_value (CELLREF row, CELLREF col, char *string)
  166. #else
  167. char *
  168. new_value (row, col, string)
  169.      CELLREF row;
  170.      CELLREF col;
  171.      char *string;
  172. #endif
  173. {
  174.   CELL *cp;
  175.  
  176.   cp = find_cell (row, col);
  177.   if (((!cp || GET_LCK (cp) == LCK_DEF) && default_lock == LCK_LCK) || (cp && GET_LCK (cp) == LCK_LCK))
  178.     {
  179.       return "cell is locked";
  180.     }
  181.  
  182.   set_cell (row, col, string);
  183.   if (my_cell)
  184.     {
  185.       update_cell (my_cell);
  186.       if (is_constant (my_cell->cell_formula))
  187.     {
  188.       byte_free (my_cell->cell_formula);
  189.       my_cell->cell_formula = 0;
  190.     }
  191.       io_pr_cell (row, col, my_cell);
  192.       my_cell = 0;
  193.     }
  194.   return 0;
  195. }
  196.  
  197. /* This sets the cell to a constant, stored in VALUE, whose type is in TYPE */
  198. #ifdef __STDC__
  199. char *
  200. set_new_value (CELLREF row, CELLREF col, int type, union vals *value)
  201. #else
  202. char *
  203. set_new_value (row, col, type, value)
  204.      CELLREF row;
  205.      CELLREF col;
  206.      int type;
  207.      union vals *value;
  208. #endif
  209. {
  210.   CELL *cp;
  211.   extern int default_lock;
  212.  
  213.   if (type == TYP_ERR)
  214.     type = 0;
  215.   cur_row = row;
  216.   cur_col = col;
  217.   if (type == 0)
  218.     {
  219.       cp = find_cell (row, col);
  220.       if (cp && GET_TYP (cp))
  221.     {
  222.       if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  223.         return "cell is locked";
  224.       my_cell = cp;
  225.       flush_old_value ();
  226.       SET_TYP (cp, 0);
  227.     }
  228.       my_cell = 0;
  229.       return 0;
  230.     }
  231.   else
  232.     {
  233.       cp = find_or_make_cell (row, col);
  234.       if ((GET_LCK (cp) == LCK_DEF && default_lock == LCK_LCK) || GET_LCK (cp) == LCK_LCK)
  235.     return "cell is locked";
  236.       my_cell = cp;
  237.       flush_old_value ();
  238.       SET_TYP (cp, type);
  239.       /* cp->c_z= *value; */
  240.       switch (type)
  241.     {
  242.     case TYP_FLT:
  243.       cp->cell_flt = value->c_d;
  244.       cp->cell_formula = 0;
  245.       break;
  246.  
  247.     case TYP_INT:
  248.       cp->cell_int = value->c_l;
  249.       cp->cell_formula = 0;
  250.       break;
  251.  
  252.     case TYP_STR:
  253.       cp->cell_str = strdup (value->c_s);
  254.       cp->cell_formula = 0;
  255.       break;
  256.  
  257.     case TYP_BOL:
  258.       cp->cell_bol = value->c_i;
  259.       cp->cell_formula = 0;
  260.       break;
  261.  
  262.     case TYP_ERR:
  263.       cp->cell_err = value->c_i;
  264.       cp->cell_formula = 0;
  265.       break;
  266. #ifdef TEST
  267.     default:
  268.       panic ("Unknown type %d in set_new_value", GET_TYP (cp));
  269. #endif
  270.     }
  271.     }
  272.   push_refs (cp->cell_refs_from);
  273.   io_pr_cell (row, col, cp);
  274.   my_cell = 0;
  275.   return 0;
  276. }
  277.  
  278. /* We're reading in a cell, whose formula is FORM, and whose current value
  279.    is VAL.  Parse both of them. . .  (Parsing of VAL is quite primitive)
  280.  */
  281. #ifdef __STDC__
  282. char *
  283. read_new_value (CELLREF row, CELLREF col, char *form, char *val)
  284. #else
  285. char *
  286. read_new_value (row, col, form, val)
  287.      CELLREF row;
  288.      CELLREF col;
  289.      char *form;
  290.      char *val;
  291. #endif
  292. {
  293.   unsigned char *new_bytes;
  294.   extern double __plinf, __neinf, __nan;
  295.  
  296.   cur_row = row;
  297.   cur_col = col;
  298.   my_cell = find_or_make_cell (cur_row, cur_col);
  299.   flush_old_value ();
  300.   SET_TYP (my_cell, 0);
  301.  
  302.   if (form)
  303.     {
  304.       new_bytes = parse_and_compile (form);
  305.       my_cell->cell_formula = new_bytes;
  306.     }
  307.  
  308.   if (val)
  309.     {
  310.       if (val[0] == '"')
  311.     {
  312.       char *sp, *nsp;
  313.  
  314.       sp = val + 1;
  315.       SET_TYP (my_cell, TYP_STR);
  316.       while (*sp)
  317.         sp++;
  318.       if (*--sp != '"')
  319.         {
  320.           if (*sp == '\r' && sp[-1] == '"')
  321.         --sp;
  322.           else
  323.         panic ("Can't find \" in read_new value");
  324.         }
  325.       *sp = '\0';
  326.       nsp = my_cell->cell_str = ck_malloc (sp - val);
  327.       for (sp = val + 1; *sp;)
  328.         *nsp++ = *sp++;
  329.       *nsp++ = '\0';
  330.     }
  331.       else if (isdigit (val[0]) || val[0] == '.' || val[0] == '-' || val[0] == '+')
  332.     {
  333.       char *v;
  334.  
  335.       v = val;
  336.       SET_TYP (my_cell, TYP_INT);
  337.       my_cell->cell_int = astol (&v);
  338.       if (*v)
  339.         {
  340.           SET_TYP (my_cell, TYP_FLT);
  341.           v = val;
  342.           my_cell->cell_flt = astof (&v);
  343.           if (*v)
  344.         return "unknown number";
  345.         }
  346.     }
  347.       else if (val[0] == '#')
  348.     {
  349.       char **en;
  350.  
  351.       if (!stricmp (tname, val))
  352.         {
  353.           SET_TYP (my_cell, TYP_BOL);
  354.           my_cell->cell_bol = 1;
  355.         }
  356.       else if (!stricmp (fname, val))
  357.         {
  358.           SET_TYP (my_cell, TYP_BOL);
  359.           my_cell->cell_bol = 0;
  360.         }
  361.       else if (!stricmp (iname, val))
  362.         {
  363.           SET_TYP (my_cell, TYP_FLT);
  364.           my_cell->cell_flt = __plinf;
  365.         }
  366.       else if (!stricmp (iname, val))
  367.         {
  368.           SET_TYP (my_cell, TYP_FLT);
  369.           my_cell->cell_flt = __plinf;
  370.         }
  371.       else if (!stricmp (mname, val))
  372.         {
  373.           SET_TYP (my_cell, TYP_FLT);
  374.           my_cell->cell_flt = __neinf;
  375.         }
  376.       else if (!stricmp (nname, val))
  377.         {
  378.           SET_TYP (my_cell, TYP_FLT);
  379.           my_cell->cell_flt = __nan;
  380.         }
  381.       else
  382.         {
  383.           SET_TYP (my_cell, TYP_ERR);
  384.           for (en = ename; *en; en++)
  385.         if (!stricmp (*en, val))
  386.           break;
  387.           if (*en)
  388.         my_cell->cell_err = en - &ename[0];
  389.           else
  390.         my_cell->cell_err = 1;
  391.         }
  392.     }
  393.       else
  394.     panic ("What is a '%s'?", val);
  395.     }
  396.  
  397.   my_cell = 0;
  398.   return 0;
  399. }
  400.  
  401. /* This moves the contents, format, etc from RF,CF to RT,CT  RF or RT may be
  402.    NON_ROW, in which case the cell's contents are moved to/from a static
  403.    storage area.  Moving anything from NON_ROW before moving anything into it
  404.    or moving two things at a time into NON_ROW are both bad ideas. . .
  405.  
  406.    Also note that move_cell does not call move_outside, which may or may not
  407.    be a bug. . .  Move_cell is only called as part of sorting, which is why
  408.    we may *not* want to call move_outside. . .
  409.  */
  410.  
  411. #ifdef __STDC__
  412. void
  413. move_cell (CELLREF rf, CELLREF cf, CELLREF rt, CELLREF ct)
  414. #else
  415. void
  416. move_cell (rf, cf, rt, ct)
  417.      CELLREF rf;
  418.      CELLREF cf;
  419.      CELLREF rt;
  420.      CELLREF ct;
  421. #endif
  422. {
  423.   CELL *cpf;
  424.  
  425.   static CELLREF non_rf, non_cf;
  426.   static struct cell non_cell;
  427.  
  428.   if (rf == NON_ROW)
  429.     {
  430.       cur_row = rt;
  431.       cur_col = ct;
  432.       my_cell = find_cell (cur_row, cur_col);
  433.       if (my_cell)
  434.     flush_old_value ();
  435.       else if (!non_cell.cell_flags && !non_cell.cell_formula
  436.            && !non_cell.cell_font)
  437.     return;
  438.       else
  439.     my_cell = find_or_make_cell (cur_row, cur_col);
  440.  
  441.       my_cell->cell_flags = non_cell.cell_flags;
  442.       my_cell->cell_refs_to = non_cell.cell_refs_to;
  443.       my_cell->cell_formula = non_cell.cell_formula;
  444.       my_cell->cell_cycle = non_cell.cell_cycle;
  445.       my_cell->cell_font = non_cell.cell_font;
  446.       my_cell->c_z = non_cell.c_z;
  447.       push_refs (my_cell->cell_refs_from);
  448.       if (my_cell->cell_refs_to)
  449.     shift_formula (cur_row, cur_col, rt - non_rf, ct - non_cf);
  450.       my_cell = 0;
  451.       return;
  452.     }
  453.  
  454.   cpf = find_cell (rf, cf);
  455.  
  456.   if (rt == NON_ROW)
  457.     {
  458.       non_rf = rf;
  459.       non_cf = cf;
  460.       if (!cpf)
  461.     bzero (&non_cell, sizeof (non_cell));
  462.       else
  463.     {
  464.       non_cell.cell_flags = cpf->cell_flags;
  465.       non_cell.cell_refs_to = cpf->cell_refs_to;
  466.       non_cell.cell_formula = cpf->cell_formula;
  467.       non_cell.cell_cycle = cpf->cell_cycle;
  468.       non_cell.cell_font = cpf->cell_font;
  469.       non_cell.c_z = cpf->c_z;
  470.       cpf->cell_flags = 0;
  471.       cpf->cell_refs_to = 0;
  472.       cpf->cell_formula = 0;
  473.       cpf->cell_cycle = 0;
  474.       cpf->cell_font = 0;
  475.     }
  476.       return;
  477.     }
  478.  
  479.   cur_row = rt;
  480.   cur_col = ct;
  481.   my_cell = find_cell (cur_row, cur_col);
  482.   if ((!cpf || (!cpf->cell_flags && !cpf->cell_formula && !cpf->cell_font))
  483.       && !my_cell)
  484.     return;
  485.   if (!my_cell)
  486.     {
  487.       my_cell = find_or_make_cell (cur_row, cur_col);
  488.       cpf = find_cell (rf, cf);    /* FOO */
  489.     }
  490.   else
  491.     flush_old_value ();
  492.  
  493.   if (!cpf)
  494.     return;
  495.  
  496.   my_cell->cell_flags = cpf->cell_flags;
  497.   my_cell->cell_refs_to = cpf->cell_refs_to;
  498.   my_cell->cell_formula = cpf->cell_formula;
  499.   my_cell->cell_cycle = cpf->cell_cycle;
  500.   my_cell->cell_font = cpf->cell_font;
  501.   my_cell->c_z = cpf->c_z;
  502.  
  503.   cpf->cell_flags = 0;
  504.   cpf->cell_refs_to = 0;
  505.   cpf->cell_formula = 0;
  506.   cpf->cell_cycle = 0;
  507.   cpf->cell_font = 0;
  508.  
  509.   push_refs (my_cell->cell_refs_from);
  510.   if (my_cell->cell_refs_to)
  511.     shift_formula (cur_row, cur_col, rt - rf, ct - cf);
  512.   my_cell = 0;
  513. }
  514.  
  515. #ifdef __STDC__
  516. void
  517. copy_cell (CELLREF rf, CELLREF cf, CELLREF rt, CELLREF ct)
  518. #else
  519. void
  520. copy_cell (rf, cf, rt, ct)
  521.      CELLREF rf;
  522.      CELLREF cf;
  523.      CELLREF rt;
  524.      CELLREF ct;
  525. #endif
  526. {
  527.   CELL *cpf;
  528.  
  529.   cpf = find_cell (rf, cf);
  530.   cur_row = rt;
  531.   cur_col = ct;
  532.   my_cell = find_cell (cur_row, cur_col);
  533.   if ((!cpf || (!cpf->cell_flags && !cpf->cell_formula && !cpf->cell_font))
  534.       && !my_cell)
  535.     return;
  536.   if (!my_cell)
  537.     {
  538.       my_cell = find_or_make_cell (cur_row, cur_col);
  539.       cpf = find_cell (rf, cf);    /* FOO */
  540.     }
  541.   else
  542.     flush_old_value ();
  543.  
  544.   if (!cpf)
  545.     return;
  546.  
  547.   my_cell->cell_flags = cpf->cell_flags;
  548.   my_cell->cell_cycle = cpf->cell_cycle;
  549.   my_cell->cell_font = cpf->cell_font;
  550.   my_cell->cell_refs_to = cpf->cell_refs_to;
  551.  
  552.   if (my_cell->cell_refs_to)
  553.     my_cell->cell_refs_to->refs_refcnt++;
  554.  
  555.   if (GET_TYP (my_cell) == TYP_STR)
  556.     my_cell->cell_str = strdup (cpf->cell_str);
  557.   else
  558.     my_cell->c_z = cpf->c_z;
  559.  
  560.   if (cpf->cell_formula)
  561.     {
  562.       unsigned char *fp;
  563.       unsigned char *hi;
  564.       unsigned char byte;
  565.       CELLREF trr, tcc;
  566.       struct rng trng;
  567.       struct function *f;
  568.       size_t len;
  569.       struct var *v;
  570.       CELL *tcp;
  571.  
  572.       fp = cpf->cell_formula;
  573.       hi = 0;
  574.       if (!moving)
  575.     moving = init_stack ();
  576.       while ((byte = *fp++) != ENDCOMP)
  577.     {
  578.       unsigned char * refloc = fp - 1;
  579.       if (byte < USR1)
  580.         f = &the_funs[byte];
  581.       else if (byte < SKIP)
  582.         {
  583.           int tmp;
  584. #ifdef TEST
  585.           if (byte - USR1 >= n_usr_funs)
  586.         panic ("Only have %d usr-function slots, but found byte for slot %d", n_usr_funs, 1 + byte - USR1);
  587. #endif
  588.           tmp = *fp++;
  589.           f = &usr_funs[byte - USR1][tmp];
  590.         }
  591.       else
  592.         f = &skip_funs[byte - SKIP];
  593.  
  594.       if (f->fn_argn & X_J)
  595.         fp++;
  596.       else if (f->fn_argn & X_JL)
  597.         fp += 2;
  598.  
  599.       if ((f->fn_argn & X_ARGS) == X_AN)
  600.         fp++;
  601.  
  602.       switch (byte)
  603.         {
  604.         case CONST_FLT:
  605.           fp += sizeof (double);
  606.           break;
  607.  
  608.         case CONST_INT:
  609.           fp += sizeof (long);
  610.           break;
  611.  
  612.         case CONST_STR:
  613.           if (!hi)
  614.         hi = fp + fp[-1];
  615.           break;
  616.  
  617.         case CONST_STR_L:
  618.           if (!hi)
  619.         hi = fp + fp[-2] + ((unsigned) (fp[-1]) << 8);
  620.           break;
  621.  
  622.         case CONST_ERR:
  623.           fp += 1 /* +sizeof(char *) */ ;
  624.           break;
  625.  
  626.         case VAR:
  627.           bcopy (fp, &v, sizeof (struct var *));
  628.           fp += sizeof (struct var *);
  629.           add_ref_fm (&(v->var_ref_fm), cur_row, cur_col);
  630.           switch (v->var_flags)
  631.         {
  632.         case VAR_UNDEF:
  633.           break;
  634.         case VAR_CELL:
  635.           tcp = find_cell (v->v_rng.lr, v->v_rng.lc);
  636.           add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  637.           break;
  638.         case VAR_RANGE:
  639.           add_range_ref (&(v->v_rng));
  640.           /* sparse array bug fixed here */
  641.           my_cell = find_cell (cur_row, cur_col);
  642.           cpf = find_cell (rf, cf);
  643.           break;
  644.         }
  645.           break;
  646.  
  647.         case R_CELL:
  648.         case R_CELL | COLREL:
  649.         case R_CELL | ROWREL:
  650.         case R_CELL | ROWREL | COLREL:
  651.           push_stack (moving, fp);
  652.           fp += EXP_ADD;
  653.           break;
  654.  
  655.         case RANGE:
  656.         case RANGE | LRREL:
  657.         case RANGE | LRREL | LCREL:
  658.         case RANGE | LRREL | LCREL | HCREL:
  659.         case RANGE | LRREL | HCREL:
  660.         case RANGE | LRREL | HRREL:
  661.         case RANGE | LRREL | HRREL | LCREL:
  662.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  663.         case RANGE | LRREL | HRREL | HCREL:
  664.         case RANGE | HRREL:
  665.         case RANGE | HRREL | LCREL:
  666.         case RANGE | HRREL | LCREL | HCREL:
  667.         case RANGE | HRREL | HCREL:
  668.         case RANGE | LCREL:
  669.         case RANGE | LCREL | HCREL:
  670.         case RANGE | HCREL:
  671.           push_stack (moving, fp);
  672.           fp += EXP_ADD_RNG;
  673.           break;
  674.  
  675.         default:
  676.           {
  677.         struct function *fun;
  678.  
  679.         if (byte >= SKIP)
  680.           break;
  681.         
  682.         if (byte < USR1)
  683.           fun = &the_funs[byte];
  684.         else
  685.            fun = &usr_funs[byte - USR1][refloc[1]];
  686.         
  687.         if (fun->fn_comptype & C_T)
  688.           {
  689.             add_ref_fm (&timer_cells, rt, ct);
  690.             ++timer_active;
  691.           }
  692.         break;
  693.           }
  694.         }
  695.     }
  696.       if (!hi)
  697.     hi = fp;
  698.       else
  699.     hi += strlen ((char *) hi);
  700.       hi++;
  701.       len = hi - cpf->cell_formula;
  702.       my_cell->cell_formula = cpf->cell_formula;
  703.       cpf->cell_formula = ck_malloc (hi - cpf->cell_formula);
  704.       if (len)
  705.     bcopy (my_cell->cell_formula, cpf->cell_formula, len);
  706.       while (fp = pop_stack (moving))
  707.     {
  708.       byte = fp[-1];
  709.       if ((byte | ROWREL | COLREL) == (R_CELL | ROWREL | COLREL))
  710.         {
  711.           trr = GET_ROW (fp);
  712.           tcc = GET_COL (fp);
  713.           if (byte & ROWREL)
  714.         {
  715.           trr += rt - rf;
  716.           PUT_ROW (fp, trr);
  717.         }
  718.           if (byte & COLREL)
  719.         {
  720.           tcc += ct - cf;
  721.           PUT_COL (fp, tcc);
  722.         }
  723.           tcp = find_or_make_cell (trr, tcc);
  724.           add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  725.         }
  726. #ifdef TEST
  727.       else if ((byte | LRREL | HRREL | LCREL | HCREL) !=
  728.            (RANGE | LRREL | HRREL | LCREL | HCREL))
  729.         panic ("Unknown byte %x in copy_cell", byte);
  730. #endif
  731.       else
  732.         {
  733.           GET_RNG (fp, &trng);
  734.           if (byte & LRREL)
  735.         trng.lr += rt - rf;
  736.           if (byte & HRREL)
  737.         trng.hr += rt - rf;
  738.           if (byte & LCREL)
  739.         trng.lc += ct - cf;
  740.           if (byte & HCREL)
  741.         trng.hc += ct - cf;
  742.           PUT_RNG (fp, &trng);
  743.           add_range_ref (&trng);
  744.           /* sparse array bug fixed here */
  745.           my_cell = find_cell (cur_row, cur_col);
  746.           cpf = find_cell (rf, cf);
  747.         }
  748.     }
  749.       update_cell (my_cell);
  750.     }
  751.   else
  752.     {
  753.       my_cell->cell_formula = 0;
  754.     }
  755.   io_pr_cell (cur_row, cur_col, my_cell);
  756.  
  757.   push_refs (my_cell->cell_refs_from);
  758.   my_cell = 0;
  759. }
  760.  
  761. /* Take away the value of CP.  This means getting rid of all the references
  762.    to it, etc.
  763.  */
  764. #ifdef __STDC__
  765. void
  766. flush_old_value (void)
  767. #else
  768. void
  769. flush_old_value ()
  770. #endif
  771. {
  772.   struct ref_to *ref;
  773.   unsigned char *refloc;
  774.   int n;
  775.   unsigned char byte;
  776.   CELL *other_cell;
  777.   struct var *varp;
  778.  
  779.   ref = my_cell->cell_refs_to;
  780.   if (ref)
  781.     {
  782.       for (n = 0; n < ref->refs_used; n++)
  783.     {
  784.       /* Switch on formula[ref->to_refs[n]] */
  785.       refloc = &(my_cell->cell_formula[ref->to_refs[n]]);
  786.       byte = refloc[0];
  787.       switch (byte)
  788.         {
  789.         case F_ROW:
  790.         case F_COL:
  791.           break;
  792.  
  793.         case R_CELL:
  794.         case R_CELL | ROWREL:
  795.         case R_CELL | COLREL:
  796.         case R_CELL | ROWREL | COLREL:
  797.           other_cell = find_cell (GET_ROW (refloc + 1), GET_COL (refloc + 1));
  798.           if (other_cell)
  799.         flush_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  800. #ifdef TEST
  801.           else
  802.         io_error_msg ("Can't find other_cell in flush_old_value");
  803. #endif
  804.           break;
  805.         case RANGE:
  806.         case RANGE | LRREL:
  807.         case RANGE | LRREL | LCREL:
  808.         case RANGE | LRREL | LCREL | HCREL:
  809.         case RANGE | LRREL | HCREL:
  810.         case RANGE | LRREL | HRREL:
  811.         case RANGE | LRREL | HRREL | LCREL:
  812.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  813.         case RANGE | LRREL | HRREL | HCREL:
  814.         case RANGE | HRREL:
  815.         case RANGE | HRREL | LCREL:
  816.         case RANGE | HRREL | LCREL | HCREL:
  817.         case RANGE | HRREL | HCREL:
  818.         case RANGE | LCREL:
  819.         case RANGE | LCREL | HCREL:
  820.         case RANGE | HCREL:
  821.           {
  822.         struct rng rng;
  823.  
  824.         GET_RNG (refloc + 1, &rng);
  825.         flush_range_ref (&rng, cur_row, cur_col);
  826.           }
  827.           break;
  828.  
  829.         case VAR:
  830.           bcopy (&refloc[1], &varp, sizeof (struct var *));
  831.           flush_ref_fm (&(varp->var_ref_fm), cur_row, cur_col);
  832.           if (varp->var_flags == VAR_CELL)
  833.         {
  834.           other_cell = find_cell (varp->v_rng.lr, varp->v_rng.lc);
  835.           if (other_cell)
  836.             flush_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  837.         }
  838.           else if (varp->var_flags == VAR_RANGE)
  839.         flush_range_ref (&(varp->v_rng), cur_row, cur_col);
  840. #ifdef TEST
  841.           else if (varp->var_flags != VAR_UNDEF)
  842.         panic ("Unknown var type %d", varp->var_flags);
  843. #endif
  844.           break;
  845.  
  846.         default:
  847.           {
  848.         struct function *fun;
  849.  
  850.         if (byte < USR1)
  851.           fun = &the_funs[byte];
  852. #ifdef TEST
  853.         else if (byte >= SKIP)
  854.           fun = 0, panic ("SKIP? in flush_old_value()");
  855. #endif
  856.         else
  857.           fun = &usr_funs[byte - USR1][refloc[1]];
  858.  
  859.         if (fun->fn_comptype & C_T)
  860.           {
  861. #ifdef TEST
  862.             if (!timer_cells || !timer_cells->refs_used)
  863.               panic ("No timer cells in flush_timer_cell");
  864. #endif
  865.             flush_ref_fm (&timer_cells, cur_row, cur_col);
  866.             --timer_active;
  867.             break;
  868.           }
  869.         else
  870.           io_error_msg ("Bad ref_to of %d.%x ignored", ref->to_refs[n], byte);
  871.           }
  872.           break;
  873.         }
  874.     }
  875. #ifdef SPLIT_REFS
  876.       ref->refs_used = 0;
  877. #else
  878.       flush_ref_to (&(my_cell->cell_refs_to));
  879. #endif
  880.     }
  881.   if (my_cell->cell_formula)
  882.     {
  883.       byte_free (my_cell->cell_formula);
  884.       my_cell->cell_formula = 0;
  885.     }
  886.   if (GET_TYP (my_cell) == TYP_STR)
  887.     free (my_cell->cell_str);
  888.   SET_TYP (my_cell, 0);
  889. }
  890.  
  891. /* --------- Routines for dealing with cell references to other cells ------ */
  892.  
  893. #ifdef __STDC__
  894. void
  895. add_ref (CELLREF row, CELLREF col)
  896. #else
  897. void
  898. add_ref (row, col)
  899.      CELLREF row;
  900.      CELLREF col;
  901. #endif
  902. {
  903.   CELL *other_cell;
  904.  
  905.   other_cell = find_or_make_cell (row, col);
  906.   add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  907. }
  908.  
  909. #ifdef __STDC__
  910. void
  911. add_range_ref (struct rng *rng)
  912. #else
  913. void
  914. add_range_ref (rng)
  915.      struct rng *rng;
  916. #endif
  917. {
  918.   CELL *other_cell;
  919.   struct ref_fm *oldref, *newref;
  920.   struct ref_fm nonref;
  921.  
  922.  
  923.   make_cells_in_range (rng);
  924.  
  925.   /* Be efficient:  If cells in the range currently have the same
  926.    * references, they'll have the same references afterward, so just
  927.    * adjust the refcounts
  928.    */
  929.   nonref.refs_refcnt = 1;
  930.   other_cell = next_cell_in_range ();
  931.   oldref = other_cell->cell_refs_from;
  932.   if (oldref && oldref->refs_refcnt == 1)
  933.     oldref = &nonref;
  934.  
  935.   add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  936.   newref = other_cell->cell_refs_from;
  937.   while (other_cell = next_cell_in_range ())
  938.     {
  939.       if (other_cell->cell_refs_from == oldref)
  940.     {
  941.       if (oldref)
  942.         {
  943.           if (oldref->refs_refcnt == 1)
  944.         {
  945.           flush_fm_ref (oldref);
  946.           oldref = &nonref;
  947.         }
  948.           else
  949.         oldref->refs_refcnt--;
  950.         }
  951.       other_cell->cell_refs_from = newref;
  952.       newref->refs_refcnt++;
  953.     }
  954.       else if (oldref == &nonref && (!other_cell->cell_refs_from || other_cell->cell_refs_from->refs_refcnt > 1))
  955.     {
  956.       oldref = other_cell->cell_refs_from;
  957.       add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  958.       newref = other_cell->cell_refs_from;
  959.     }
  960.       else
  961.     add_ref_fm (&(other_cell->cell_refs_from), cur_row, cur_col);
  962.     }
  963.   /* if(oldref && oldref->refs_refcnt==0) {
  964.         oldref->refs_refcnt=1;
  965.         flush_fm_ref(oldref);
  966.     } */
  967. }
  968.  
  969. #ifdef __STDC__
  970. static void
  971. flush_range_ref (struct rng *rng, CELLREF rr, CELLREF cc)
  972. #else
  973. static void
  974. flush_range_ref (rng, rr, cc)
  975.      struct rng *rng;
  976.      CELLREF rr;
  977.      CELLREF cc;
  978. #endif
  979. {
  980.   CELL *other_cell;
  981. #ifndef SPLIT_REFS
  982.   struct ref_fm *oldref, *newref;
  983.   struct ref_fm nonref;
  984. #endif
  985.   /* This is horribly inefficient:  Simply referencing a cell makes
  986.        it appear.  On the other hand, there is no other easy way to deal
  987.        with the references to the cells (That I know of, anyway) */
  988.   find_cells_in_range (rng);
  989. #ifndef SPLIT_REFS
  990.   /* Be efficient:  If cells in the range currently have the same
  991.        references, they'll have the same references afterward, so just
  992.        adjust the refcounts */
  993.   nonref.refs_refcnt = 1;
  994.   other_cell = next_cell_in_range ();
  995.   if (!other_cell)
  996.     return;
  997.   oldref = other_cell->cell_refs_from;
  998.   if (oldref && oldref->refs_refcnt == 1)
  999.     oldref = &nonref;
  1000.  
  1001.   flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1002.   newref = other_cell->cell_refs_from;
  1003.   while (other_cell = next_cell_in_range ())
  1004.     {
  1005.       if (other_cell->cell_refs_from == oldref)
  1006.     {
  1007.       if (oldref)
  1008.         {
  1009.           if (oldref->refs_refcnt == 1)
  1010.         {
  1011.           flush_fm_ref (oldref);
  1012.           oldref = &nonref;
  1013.         }
  1014.           else
  1015.         oldref->refs_refcnt--;
  1016.         }
  1017.       other_cell->cell_refs_from = newref;
  1018.       if (newref)
  1019.         newref->refs_refcnt++;
  1020.     }
  1021.       else if (oldref == &nonref && (!other_cell->cell_refs_from || other_cell->cell_refs_from->refs_refcnt > 1))
  1022.     {
  1023.       oldref = other_cell->cell_refs_from;
  1024.       flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1025.       newref = other_cell->cell_refs_from;
  1026.     }
  1027.       else
  1028.     flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1029.     }
  1030. #else
  1031.   while (other_cell = next_cell_in_range ())
  1032.     flush_ref_fm (&(other_cell->cell_refs_from), rr, cc);
  1033. #endif
  1034. }
  1035.  
  1036. /* SPLIT_REFS should probably go away, since it is a performance loss.
  1037.    When it is defined, we allocate a a reference structure for each cell with
  1038.    references, and update them individually.
  1039.  
  1040.    The default is to allocate one reference structure for each *different*
  1041.    reference, and have multiple cells point to it.  We use reference counts
  1042.    to keep track of when to delete the reference structure.  This would
  1043.    appear to be a performance loss, but because of the increased efficiency
  1044.    in referencing ranges, it may actually be faster.  It also uses *far* less
  1045.    memory than SPLIT_REFS */
  1046.  
  1047.  
  1048. #ifndef SPLIT_REFS
  1049. #ifdef __TURBOC__
  1050. #define FM_HASH_NUM 51
  1051. #define TO_HASH_NUM 13
  1052. #else
  1053. #define FM_HASH_NUM 503
  1054. #define TO_HASH_NUM 29
  1055. #endif
  1056. #ifdef TEST
  1057. static int fm_misses = 0;
  1058. static int to_misses = 0;
  1059. #endif
  1060.  
  1061. static struct ref_fm *fm_list[FM_HASH_NUM];
  1062. static struct ref_fm *fm_tmp_ref;
  1063. static unsigned fm_tmp_ref_alloc;
  1064.  
  1065. static struct ref_to *to_list[TO_HASH_NUM];
  1066. static struct ref_to *to_tmp_ref;
  1067. static unsigned to_tmp_ref_alloc;
  1068.  
  1069. #ifdef __STDC__
  1070. void
  1071. flush_refs (void)
  1072. #else
  1073. void
  1074. flush_refs ()
  1075. #endif
  1076. {
  1077.   int n;
  1078.   struct ref_fm *ftmp, *oftmp;
  1079.   struct ref_to *ttmp, *ottmp;
  1080.  
  1081.   for (n = 0; n < FM_HASH_NUM; n++)
  1082.     {
  1083.       for (ftmp = fm_list[n]; ftmp; ftmp = oftmp)
  1084.     {
  1085.       oftmp = ftmp->refs_next;
  1086.       free (ftmp);
  1087.     }
  1088.       fm_list[n] = 0;
  1089.     }
  1090.   for (n = 0; n < TO_HASH_NUM; n++)
  1091.     {
  1092.       for (ttmp = to_list[n]; ttmp; ttmp = ottmp)
  1093.     {
  1094.       ottmp = ttmp->refs_next;
  1095.       free (ttmp);
  1096.     }
  1097.       to_list[n] = 0;
  1098.     }
  1099. }
  1100.  
  1101. #ifdef __STDC__
  1102. static struct ref_fm *
  1103. find_fm_ref (void)
  1104. #else
  1105. static struct ref_fm *
  1106. find_fm_ref ()
  1107. #endif
  1108. {
  1109.   struct ref_fm *tmp;
  1110.   int n;
  1111.   unsigned long hash;
  1112.  
  1113. #if 1
  1114.   for (hash = 0, n = 0; n < fm_tmp_ref->refs_used; n++)
  1115.     {
  1116.       hash += (n + 1) * (((fm_tmp_ref->fm_refs[n].ref_row) << BITS_PER_CELLREF) +
  1117.              fm_tmp_ref->fm_refs[n].ref_col);
  1118.     }
  1119.   hash %= FM_HASH_NUM;
  1120. #else
  1121.   hash = fm_tmp_ref->refs_used;
  1122. #endif
  1123.   for (tmp = fm_list[hash]; tmp; tmp = tmp->refs_next)
  1124.     {
  1125.       if (tmp->refs_used != fm_tmp_ref->refs_used)
  1126.     continue;
  1127.       if (!bcmp (tmp->fm_refs, fm_tmp_ref->fm_refs, fm_tmp_ref->refs_used * sizeof (struct ref_array)))
  1128.     {
  1129.       tmp->refs_refcnt++;
  1130.       return tmp;
  1131.     }
  1132. #ifdef TEST
  1133.       else
  1134.     fm_misses++;
  1135. #endif
  1136.     }
  1137.  
  1138.   tmp = ck_malloc (sizeof (struct ref_fm) + (fm_tmp_ref->refs_used - 1) * sizeof (struct ref_array));
  1139.   tmp->refs_next = fm_list[hash];
  1140.   fm_list[hash] = tmp;
  1141.   tmp->refs_refcnt = 1;
  1142.   tmp->refs_used = fm_tmp_ref->refs_used;
  1143.   if (tmp->refs_used)
  1144.     bcopy (fm_tmp_ref->fm_refs, tmp->fm_refs,
  1145.        tmp->refs_used * sizeof (struct ref_array));
  1146.  
  1147.   return tmp;
  1148. }
  1149.  
  1150. #ifdef __STDC__
  1151. static void 
  1152. flush_fm_ref (struct ref_fm *old)
  1153. #else
  1154. static void 
  1155. flush_fm_ref (old)
  1156.      struct ref_fm *old;
  1157. #endif
  1158. {
  1159.   struct ref_fm *tmp;
  1160.   int n;
  1161.   unsigned long hash;
  1162.  
  1163.   --(old->refs_refcnt);
  1164.  
  1165. #ifdef DEFER_FREE
  1166.   return;
  1167. #endif
  1168.   if (!old->refs_refcnt)
  1169.     {
  1170. #if 1
  1171.       for (hash = 0, n = 0; n < old->refs_used; n++)
  1172.     {
  1173.       hash += (n + 1) * (((old->fm_refs[n].ref_row) << BITS_PER_CELLREF) +
  1174.                  old->fm_refs[n].ref_col);
  1175.     }
  1176.       hash %= FM_HASH_NUM;
  1177. #else
  1178.       hash = old->refs_used;
  1179. #endif
  1180.       if (fm_list[hash] == old)
  1181.     fm_list[hash] = old->refs_next;
  1182.       else
  1183.     {
  1184.       for (tmp = fm_list[hash]; tmp && tmp->refs_next != old; tmp = tmp->refs_next)
  1185.         ;
  1186. #ifdef TEST
  1187.       if (!tmp)
  1188.         {
  1189.           io_error_msg ("Old not in refs_list in flush_fm_ref(%p)", old);
  1190.           return;
  1191.         }
  1192. #endif
  1193.       tmp->refs_next = old->refs_next;
  1194.     }
  1195.       free (old);
  1196.     }
  1197. }
  1198.  
  1199. /* This adds a from reference to a cells reference list.
  1200.  * Note that the ref_fm structures themselves are hash-consed.
  1201.  */
  1202. #ifdef __STDC__
  1203. static void
  1204. add_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1205. #else
  1206. static void
  1207. add_ref_fm (where, r, c)
  1208.      struct ref_fm **where;
  1209.      CELLREF r;
  1210.      CELLREF c;
  1211. #endif
  1212. {
  1213.   struct ref_fm *from;
  1214.   int n;
  1215.  
  1216.   from = *where;
  1217.   if (!from)
  1218.     {
  1219.       if (!fm_tmp_ref)
  1220.     {
  1221.       fm_tmp_ref = ck_malloc (sizeof (struct ref_fm));
  1222.       fm_tmp_ref_alloc = 1;
  1223.     }
  1224.       fm_tmp_ref->refs_used = 1;
  1225.       fm_tmp_ref->fm_refs[0].ref_row = r;
  1226.       fm_tmp_ref->fm_refs[0].ref_col = c;
  1227.     }
  1228.   else
  1229.     {
  1230.       if (fm_tmp_ref_alloc <= from->refs_used)
  1231.     {
  1232.       fm_tmp_ref =
  1233.         ck_realloc (fm_tmp_ref, sizeof (struct ref_fm)
  1234.             + from->refs_used * sizeof (struct ref_array)) ;
  1235.       fm_tmp_ref_alloc = from->refs_used + 1;
  1236.     }
  1237.       fm_tmp_ref->refs_used = from->refs_used + 1;
  1238.       n = 0;
  1239.       while (n < from->refs_used
  1240.          && (from->fm_refs[n].ref_row < r
  1241.        || (from->fm_refs[n].ref_row == r && from->fm_refs[n].ref_col <= c)))
  1242.     {
  1243.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n];
  1244.       n++;
  1245.     }
  1246.       fm_tmp_ref->fm_refs[n].ref_row = r;
  1247.       fm_tmp_ref->fm_refs[n].ref_col = c;
  1248.       while (n < from->refs_used)
  1249.     {
  1250.       fm_tmp_ref->fm_refs[n + 1] = from->fm_refs[n];
  1251.       n++;
  1252.     }
  1253.     }
  1254.   *where = find_fm_ref ();
  1255.   if (from)
  1256.     flush_fm_ref (from);
  1257. }
  1258.  
  1259. #ifdef __STDC__
  1260. static void
  1261. flush_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1262. #else
  1263. static void
  1264. flush_ref_fm (where, r, c)
  1265.      struct ref_fm **where;
  1266.      CELLREF r;
  1267.      CELLREF c;
  1268. #endif
  1269. {
  1270.   struct ref_fm *from;
  1271.   int n;
  1272.  
  1273.   from = *where;
  1274. #ifdef TEST
  1275.   if (!from)
  1276.     {
  1277.       io_error_msg ("No refs in flush_ref_fm(%p,%u,%u)", where, r, c);
  1278.       return;
  1279.     }
  1280. #endif
  1281.   if (!from)
  1282.     return;
  1283.   if (from->refs_used == 1)
  1284.     {
  1285.       *where = 0;
  1286.       flush_fm_ref (from);
  1287.       return;
  1288.     }
  1289.   fm_tmp_ref->refs_used = from->refs_used - 1;
  1290.   n = 0;
  1291.   while (n < from->refs_used
  1292.      && (from->fm_refs[n].ref_row < r
  1293.     || (from->fm_refs[n].ref_row == r && from->fm_refs[n].ref_col < c)))
  1294.     {
  1295.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n];
  1296.       n++;
  1297.     }
  1298. #ifdef TEST
  1299.   if (n == from->refs_used)
  1300.     {
  1301.       io_error_msg ("No refs from %u,%u in %p in flush_refs_fm", r, c, where);
  1302.       return;
  1303.     }
  1304. #endif
  1305.   while (n < fm_tmp_ref->refs_used)
  1306.     {
  1307.       fm_tmp_ref->fm_refs[n] = from->fm_refs[n + 1];
  1308.       n++;
  1309.     }
  1310.   *where = find_fm_ref ();
  1311.   flush_fm_ref (from);
  1312. }
  1313.  
  1314. #ifdef TEST
  1315.  
  1316. void
  1317. dbg_print_ref_fm (rf)
  1318.      struct ref_fm *rf;
  1319. {
  1320.   int nr;
  1321.   char *bufp;
  1322.  
  1323.   if (rf)
  1324.     {
  1325.       io_text_line ("fm %p: refcnt %u  next %p  used %u",
  1326.             rf, rf->refs_refcnt, rf->refs_next, rf->refs_used);
  1327.       for (nr = 0, bufp = print_buf; nr < rf->refs_used; nr++)
  1328.     {
  1329.       (void) sprintf (bufp, " %s", cell_name (rf->fm_refs[nr].ref_row, rf->fm_refs[nr].ref_col));
  1330.       if (nr % 10 == 9)
  1331.         {
  1332.           io_text_line (print_buf);
  1333.           bufp = print_buf;
  1334.         }
  1335.       else
  1336.         bufp += strlen (bufp);
  1337.     }
  1338.       if (nr % 10)
  1339.     io_text_line (print_buf);
  1340.     }
  1341. }
  1342.  
  1343. #endif
  1344.  
  1345. #ifdef __STDC__
  1346. static struct ref_to *
  1347. find_to_ref (void)
  1348. #else
  1349. static struct ref_to *
  1350. find_to_ref ()
  1351. #endif
  1352. {
  1353.   struct ref_to *tmp;
  1354.   int n;
  1355.   unsigned long hash;
  1356.  
  1357.   /* io_error_msg("find_to_ref %u %u",to_tmp_ref->refs_used,to_tmp_ref->to_refs[0]); */
  1358. #if 1
  1359.   for (hash = 0, n = 0; n < to_tmp_ref->refs_used; n++)
  1360.     hash += (n + 1) * to_tmp_ref->to_refs[n];
  1361.  
  1362.   hash %= TO_HASH_NUM;
  1363. #else
  1364.   hash = to_tmp_ref->refs_used;
  1365. #endif
  1366.   for (tmp = to_list[hash]; tmp; tmp = tmp->refs_next)
  1367.     {
  1368.       /* io_error_msg("%p(%u)->%p  %u %u",tmp,tmp->refs_refcnt,
  1369.             tmp->refs_next,tmp->refs_used,tmp->to_refs[0]); */
  1370.       if (tmp->refs_used != to_tmp_ref->refs_used)
  1371.     continue;
  1372.       if (!bcmp (tmp->to_refs, to_tmp_ref->to_refs, to_tmp_ref->refs_used))
  1373.     {
  1374.       /* io_error_msg("Hit!"); */
  1375.       tmp->refs_refcnt++;
  1376.       return tmp;
  1377.     }
  1378. #ifdef TEST
  1379.       else
  1380.     to_misses++;
  1381. #endif
  1382.     }
  1383.  
  1384.   /* io_error_msg("Miss. .."); */
  1385.   tmp = ck_malloc (sizeof (struct ref_to) + to_tmp_ref->refs_used - 1);
  1386.   tmp->refs_next = to_list[hash];
  1387.   to_list[hash] = tmp;
  1388.   tmp->refs_refcnt = 1;
  1389.   tmp->refs_used = to_tmp_ref->refs_used;
  1390.   if (tmp->refs_used)
  1391.     bcopy (to_tmp_ref->to_refs, tmp->to_refs, tmp->refs_used);
  1392.  
  1393.   return tmp;
  1394. }
  1395.  
  1396. #ifdef __STDC__
  1397. void
  1398. add_ref_to (int whereto)
  1399. #else
  1400. void
  1401. add_ref_to (whereto)
  1402.      int whereto;
  1403. #endif
  1404. {
  1405.   struct ref_to *from;
  1406.   int n;
  1407.  
  1408.   from = my_cell->cell_refs_to;
  1409.   if (!from)
  1410.     {
  1411.       if (!to_tmp_ref)
  1412.     {
  1413.       to_tmp_ref = ck_malloc (sizeof (struct ref_to));
  1414.       to_tmp_ref_alloc = 1;
  1415.     }
  1416.       to_tmp_ref->refs_used = 1;
  1417.       to_tmp_ref->to_refs[0] = whereto;
  1418.     }
  1419.   else
  1420.     {
  1421.       if (to_tmp_ref_alloc <= from->refs_used)
  1422.     {
  1423.       to_tmp_ref = ck_realloc (to_tmp_ref, sizeof (struct ref_to) + from->refs_used);
  1424.       to_tmp_ref_alloc = from->refs_used + 1;
  1425.     }
  1426.       to_tmp_ref->refs_used = from->refs_used + 1;
  1427.       n = 0;
  1428.       while (n < from->refs_used && from->to_refs[n] < whereto)
  1429.     {
  1430.       to_tmp_ref->to_refs[n] = from->to_refs[n];
  1431.       n++;
  1432.     }
  1433.       to_tmp_ref->to_refs[n] = whereto;
  1434.       while (n < from->refs_used)
  1435.     {
  1436.       to_tmp_ref->to_refs[n + 1] = from->to_refs[n];
  1437.       n++;
  1438.     }
  1439.       flush_ref_to (&(my_cell->cell_refs_to));
  1440.     }
  1441.   my_cell->cell_refs_to = find_to_ref ();
  1442. }
  1443.  
  1444. #ifdef __STDC__
  1445. static void
  1446. flush_ref_to (struct ref_to **where)
  1447. #else
  1448. static void
  1449. flush_ref_to (where)
  1450.      struct ref_to **where;
  1451. #endif
  1452. {
  1453.   struct ref_to *tmp;
  1454.   struct ref_to *old;
  1455.   int n;
  1456.   unsigned long hash;
  1457.  
  1458. #ifdef TEST
  1459.   if (!where || !*where)
  1460.     {
  1461.       io_error_msg ("null flush_ref_to(%p)", where);
  1462.       return;
  1463.     }
  1464. #endif
  1465.   old = *where;
  1466.   *where = 0;
  1467.   --(old->refs_refcnt);
  1468.  
  1469. #ifdef DEFER_FREE
  1470.   return;
  1471. #endif
  1472.   if (!old->refs_refcnt)
  1473.     {
  1474. #if 1
  1475.       for (hash = 0, n = 0; n < old->refs_used; n++)
  1476.     hash += (n + 1) * old->to_refs[n];
  1477.  
  1478.       hash %= TO_HASH_NUM;
  1479. #else
  1480.       hash = old->refs_used;
  1481. #endif
  1482.       if (to_list[hash] == old)
  1483.     to_list[hash] = old->refs_next;
  1484.       else
  1485.     {
  1486.       for (tmp = to_list[hash]; tmp && tmp->refs_next != old; tmp = tmp->refs_next)
  1487.         ;
  1488. #ifdef TEST
  1489.       if (!tmp)
  1490.         {
  1491.           io_error_msg ("Old not in refs_list in flush_to_ref(%p)", old);
  1492.           return;
  1493.         }
  1494. #endif
  1495.       tmp->refs_next = old->refs_next;
  1496.     }
  1497.       free (old);
  1498.     }
  1499. }
  1500.  
  1501. #ifdef TEST
  1502. void
  1503. dbg_print_ref_to (rt, form)
  1504.      struct ref_to *rt;
  1505.      unsigned char *form;
  1506. {
  1507.   int nr;
  1508.   char *bufp;
  1509.  
  1510.   if (rt)
  1511.     {
  1512.       io_text_line ("to %p: refcnt %u  next %p  used %u",
  1513.             rt, rt->refs_refcnt, rt->refs_next, rt->refs_used);
  1514.       for (nr = 0, bufp = print_buf; nr < rt->refs_used; nr++)
  1515.     {
  1516.       (void) sprintf (bufp, " %3d (%#4x)", rt->to_refs[nr], form[rt->to_refs[nr]]);
  1517.       if (nr % 7 == 6)
  1518.         {
  1519.           io_text_line (print_buf);
  1520.           bufp = print_buf;
  1521.         }
  1522.       else
  1523.         bufp += strlen (bufp);
  1524.     }
  1525.       if (nr % 7)
  1526.     io_text_line (print_buf);
  1527.     }
  1528. }
  1529.  
  1530. void
  1531. ref_stats ()
  1532. {
  1533.   int n;
  1534.   int cur;
  1535.   struct ref_fm *rf;
  1536.   struct ref_to *rt;
  1537.  
  1538.   int rf_max = 0;
  1539.   int rf_num = 0;
  1540.   int rf_shared = 0;
  1541.   int rf_saved = 0;
  1542.   int rf_zero = 0;
  1543.  
  1544.   int rt_max = 0;
  1545.   int rt_num = 0;
  1546.   int rt_shared = 0;
  1547.   int rt_saved = 0;
  1548.   int rt_zero = 0;
  1549.  
  1550.   for (n = 0; n < FM_HASH_NUM; n++)
  1551.     {
  1552.       cur = 0;
  1553.       for (rf = fm_list[n]; rf; rf = rf->refs_next)
  1554.     {
  1555.       if (rf->refs_refcnt == 0)
  1556.         rf_zero++;
  1557.       if (rf->refs_refcnt > 1)
  1558.         {
  1559.           rf_shared++;
  1560.           rf_saved += rf->refs_refcnt - 1;
  1561.         }
  1562.       rf_num++;
  1563.       cur++;
  1564.     }
  1565.       if (cur > rf_max)
  1566.     rf_max = cur;
  1567.     }
  1568.   for (n = 0; n < TO_HASH_NUM; n++)
  1569.     {
  1570.       cur = 0;
  1571.       for (rt = to_list[n]; rt; rt = rt->refs_next)
  1572.     {
  1573.       if (rt->refs_refcnt == 0)
  1574.         rt_zero++;
  1575.       if (rt->refs_refcnt > 1)
  1576.         {
  1577.           rt_shared++;
  1578.           rt_saved += rt->refs_refcnt - 1;
  1579.         }
  1580.       rt_num++;
  1581.       cur++;
  1582.     }
  1583.       if (cur > rt_max)
  1584.     rt_max = cur;
  1585.     }
  1586.   io_text_line ("from: %d refs, max_length %d, shared %d, saved %d, zero_ref %d, missed %d\n", rf_num, rf_max, rf_shared, rf_saved, rf_zero, fm_misses);
  1587.   io_text_line ("to: %d refs, max_length %d, shared %d, saved %d, zero_ref %d, missed %d\n", rt_num, rt_max, rt_shared, rt_saved, rt_zero, to_misses);
  1588. }
  1589.  
  1590. #endif
  1591. #else
  1592.  
  1593. #ifdef __STDC__
  1594. static void
  1595. add_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1596. #else
  1597. static void
  1598. add_ref_fm (where, r, c)
  1599.      struct ref_fm **where;
  1600.      CELLREF r;
  1601.      CELLREF c;
  1602. #endif
  1603. {
  1604.   struct ref_fm *ref;
  1605.  
  1606.   ref = *where;
  1607.   if (!ref)
  1608.     {
  1609.       *where = ref = ck_malloc (sizeof (struct ref_fm) + (REF_START - 1) * sizeof (struct ref_array));
  1610.       ref->refs_alloc = REF_START;
  1611.       ref->refs_used = 0;
  1612.     }
  1613.   else if (ref->refs_alloc == ref->refs_used)
  1614.     {
  1615.       ref->refs_alloc REF_INC;
  1616.       *where = ref = ck_realloc (ref, sizeof (struct ref_fm) + (ref->refs_alloc - 1) * sizeof (struct ref_array));
  1617.     }
  1618.   ref->fm_refs[ref->refs_used].ref_row = r;
  1619.   ref->fm_refs[ref->refs_used].ref_col = c;
  1620.   ref->refs_used++;
  1621. }
  1622.  
  1623. #ifdef __STDC__
  1624. static void
  1625. flush_ref_fm (struct ref_fm **where, CELLREF r, CELLREF c)
  1626. #else
  1627. static void
  1628. flush_ref_fm (where, r, c)
  1629.      struct ref_fm **where;
  1630.      CELLREF r;
  1631.      CELLREF c;
  1632. #endif
  1633. {
  1634.   int n;
  1635.   struct ref_fm *ref;
  1636.  
  1637.   ref = *where;
  1638. #ifdef TEST
  1639.   if (!ref)
  1640.     {
  1641.       io_error_msg ("%s->No refs in flush_ref_fm(%d,%d)", cell_name (cur_row, cur_col), r, c);
  1642.       return;
  1643.     }
  1644. #endif
  1645.   for (n = 0; n < ref->refs_used; n++)
  1646.     if (ref->fm_refs[n].ref_row == r && ref->fm_refs[n].ref_col == c)
  1647.       {
  1648.     ref->fm_refs[n] = ref->fm_refs[ref->refs_used - 1];
  1649.     --(ref->refs_used);
  1650.     return;
  1651.       }
  1652. #ifdef TEST
  1653.   io_error_msg ("%s->Can't flush_ref_fm(%d,%d)", cell_name (cur_row, cur_col), r, c);
  1654.   return;
  1655. #endif
  1656. }
  1657.  
  1658. #ifdef __STDC__
  1659. void
  1660. add_ref_to (int whereto)
  1661. #else
  1662. void
  1663. add_ref_to (whereto)
  1664.      int whereto;
  1665. #endif
  1666. {
  1667.   struct ref_to *ref;
  1668.  
  1669.   ref = my_cell->cell_refs_to;
  1670.   if (!ref)
  1671.     {
  1672.       my_cell->cell_refs_to = ref = ck_malloc (sizeof (struct ref_to) + (REF_START - 1) * sizeof (unsigned char));
  1673.       ref->refs_alloc = REF_START;
  1674.       ref->refs_used = 0;
  1675.     }
  1676.   else if (ref->refs_alloc == ref->refs_used)
  1677.     {
  1678.       ref->refs_alloc REF_INC;
  1679.       my_cell->cell_refs_to = ref = ck_realloc (ref, sizeof (struct ref_to) +
  1680.                 (ref->refs_alloc - 1) * sizeof (unsigned char));
  1681.     }
  1682.   ref->to_refs[ref->refs_used] = whereto;
  1683.   ref->refs_used++;
  1684. }
  1685.  
  1686. #ifdef TEST
  1687.  
  1688. void
  1689. dbg_print_ref_fm (rf)
  1690.      struct ref_fm *rf;
  1691. {
  1692.   int nr;
  1693.   char *bufp;
  1694.  
  1695.   if (rf)
  1696.     {
  1697.       io_text_line ("fm %p: alloc %u  used %u",
  1698.             rf, rf->refs_alloc, rf->refs_used);
  1699.       for (nr = 0, bufp = print_buf; nr < rf->refs_used; nr++)
  1700.     {
  1701.       (void) sprintf (bufp, " %s", cell_name (rf->fm_refs[nr].ref_row, rf->fm_refs[nr].ref_col));
  1702.       if (nr % 10 == 9)
  1703.         {
  1704.           io_text_line (print_buf);
  1705.           bufp = print_buf;
  1706.         }
  1707.       else
  1708.         bufp += strlen (bufp);
  1709.     }
  1710.       if (nr % 10)
  1711.     io_text_line (print_buf);
  1712.     }
  1713. }
  1714.  
  1715. void
  1716. dbg_print_ref_to (rt, form)
  1717.      struct ref_to *rt;
  1718.      unsigned char *form;
  1719. {
  1720.   int nr;
  1721.   char *bufp;
  1722.  
  1723.   if (rt)
  1724.     {
  1725.       io_text_line ("to %p:  alloc %u  used %u",
  1726.             rt, rt->refs_alloc, rt->refs_used);
  1727.       for (nr = 0, bufp = print_buf; nr < rt->refs_used; nr++)
  1728.     {
  1729.       (void) sprintf (bufp, " %3d (%#4x)", rt->to_refs[nr], form[rt->to_refs[nr]]);
  1730.       if (nr % 7 == 6)
  1731.         {
  1732.           io_text_line (print_buf);
  1733.           bufp = print_buf;
  1734.         }
  1735.       else
  1736.         bufp += strlen (bufp);
  1737.     }
  1738.       if (nr % 7)
  1739.     io_text_line (print_buf);
  1740.     }
  1741. }
  1742.  
  1743. void
  1744. ref_stats ()
  1745. {
  1746.   CELL *cp;
  1747.  
  1748.   int rf_num = 0;
  1749.   int rf_zero = 0;
  1750.   int rf_biggest = 0;
  1751.  
  1752.   int rt_num = 0;
  1753.   int rt_zero = 0;
  1754.   int rt_biggest = 0;
  1755.  
  1756.   find_cells_in_range (&all_rng);
  1757.   while (cp = next_cell_in_range ())
  1758.     {
  1759.       if (cp->cell_refs_from)
  1760.     {
  1761.       if (cp->cell_refs_from->refs_used > rf_biggest)
  1762.         rf_biggest = cp->cell_refs_from->refs_used;
  1763.       if (cp->cell_refs_from->refs_used == 0)
  1764.         rf_zero++;
  1765.       rf_num++;
  1766.     }
  1767.       if (cp->cell_refs_to)
  1768.     {
  1769.       if (cp->cell_refs_to->refs_used > rt_biggest)
  1770.         rt_biggest = cp->cell_refs_to->refs_used;
  1771.       if (cp->cell_refs_to->refs_used == 0)
  1772.         rt_zero++;
  1773.       rt_num++;
  1774.     }
  1775.     }
  1776.   io_text_line ("from: %d refs, biggest %d, zero_ref %d\n", rf_num, rf_biggest, rf_zero);
  1777.   io_text_line ("to: %d refs, biggest %d,zero_ref %d\n", rt_num, rt_biggest, rt_zero);
  1778. }
  1779.  
  1780. #endif
  1781.  
  1782. #endif
  1783.  
  1784. /* ------------- Routines for dealing with moving cells -------------------- */
  1785.  
  1786. static struct rng *shift_fm;
  1787. static int shift_ov;
  1788. static int shift_dn;
  1789.  
  1790. /* This removes all the CELL_REF_FM links associated with a 
  1791.  * variable, and adjusts the variables value.
  1792.  * After calling this function, one must also call 
  1793.  * finish_shift_var to install the new CELL_REF_FM links.
  1794.  */
  1795. #ifdef __STDC__
  1796. static void 
  1797. start_shift_var (char *name, struct var *v)
  1798. #else
  1799. static void 
  1800. start_shift_var (name, v)
  1801.      char *name;
  1802.      struct var *v;
  1803. #endif
  1804. {
  1805.   int n;
  1806.   int nn;
  1807.  
  1808.  
  1809.   n = (BETWEEN (v->v_rng.hc, shift_fm->lc, shift_fm->hc) << 3)
  1810.     + (BETWEEN (v->v_rng.lc, shift_fm->lc, shift_fm->hc) << 2)
  1811.     + (BETWEEN (v->v_rng.hr, shift_fm->lr, shift_fm->hr) << 1)
  1812.     + BETWEEN (v->v_rng.lr, shift_fm->lr, shift_fm->hr);
  1813.   switch (n)
  1814.     {
  1815.     case 0:
  1816.     case 1:
  1817.     case 2:
  1818.     case 3:
  1819.     case 4:
  1820.     case 8:
  1821.     case 12:
  1822.       /* Null intersection, ignore it */
  1823.       break;
  1824.  
  1825.     case 5:            /* The bottom and right */
  1826.     case 6:            /* The bottom and left */
  1827.     case 9:            /* The top and right */
  1828.     case 10:            /* The top and left */
  1829.       /* The var sticks out of the range we're moving */
  1830.       /* on two sides.  what should we do? */
  1831.       io_error_msg ("'%s' can't be adjusted", v->var_name);
  1832.       break;
  1833.  
  1834.     case 7:            /* v->hc sticks out the right */
  1835.     case 11:            /* v->lc sticks out the left */
  1836.     case 13:            /* v->hr sticks out the bottom */
  1837.     case 14:            /* v->lr sticks out the top */
  1838.       /* It only sticks out on one side.  We can
  1839.            (try to) adjust it */
  1840.  
  1841.     case 15:            /* var is completely inside the range */
  1842.       if (v->var_ref_fm)
  1843.     {
  1844.       for (nn = 0; nn < v->var_ref_fm->refs_used; nn++)
  1845.         {
  1846.           flush_range_ref (&(v->v_rng),
  1847.                    v->var_ref_fm->fm_refs[nn].ref_row,
  1848.                    v->var_ref_fm->fm_refs[nn].ref_col);
  1849.         }
  1850.     }
  1851.       if (n != 7)
  1852.     v->v_rng.hc += shift_ov;
  1853.       if (n != 11)
  1854.     v->v_rng.lc += shift_ov;
  1855.       if (n != 13)
  1856.     v->v_rng.hr += shift_dn;
  1857.       if (n != 14)
  1858.     v->v_rng.lr += shift_dn;
  1859.       v->var_flags = VAR_DANGLING_RANGE;
  1860.     }
  1861. }
  1862.  
  1863.  
  1864. #ifdef __STDC__
  1865. static void 
  1866. finish_shift_var (char *name, struct var *v)
  1867. #else
  1868. static void 
  1869. finish_shift_var (name, v)
  1870.      char *name;
  1871.      struct var *v;
  1872. #endif
  1873. {
  1874.   int n;
  1875.   if (!v->var_ref_fm || v->var_flags != VAR_DANGLING_RANGE)
  1876.     return;
  1877.  
  1878.   v->var_flags = VAR_RANGE;
  1879.  
  1880.   for (n = 0; n < v->var_ref_fm->refs_used; n++)
  1881.     {
  1882.       cur_row = v->var_ref_fm->fm_refs[n].ref_row;
  1883.       cur_col = v->var_ref_fm->fm_refs[n].ref_col;
  1884.       add_range_ref (&(v->v_rng));
  1885.     }
  1886. }
  1887.  
  1888. #define RIGHT    8
  1889. #define LEFT    4
  1890. #define BOTTOM    2
  1891. #define TOP    1
  1892.  
  1893. /*
  1894.  * This iterates over the region FM, preparing the cells there to be shifted
  1895.  * OV(er) and D(ow)N.
  1896.  *
  1897.  * After this, the ref_fm and ref_to lists of a cell within the region should
  1898.  * be appropriate to the location that cell will be shifted to.
  1899.  * 
  1900.  * Variables and references to variables are also shifted.
  1901.  */
  1902. #ifdef __STDC__
  1903. void
  1904. shift_outside (struct rng *fm, int dn, int ov)
  1905. #else
  1906. void
  1907. shift_outside (fm, dn, ov)
  1908.      struct rng *fm;
  1909.      int dn;
  1910.      int ov;
  1911. #endif
  1912. {
  1913.   CELL *cp;
  1914.   CELL *fcp;
  1915.   CELL *tcp;
  1916.   int n;
  1917.   int fn;
  1918.   CELLREF rr, cc;
  1919.   CELLREF frr, fcc;
  1920.   CELLREF trr, tcc;
  1921.   unsigned char *ffp;
  1922.   unsigned char *fp;
  1923.   struct rng orng;
  1924.  
  1925.   char *ptr;
  1926.   unsigned long val;
  1927.   static char DEF_REF[] = "DEFREF";
  1928.   static char DEF_RNG[] = "DEFRNG";
  1929.  
  1930.   /* Variables and references to variables are also shifted. */
  1931.   shift_fm = fm;
  1932.   shift_dn = dn;
  1933.   shift_ov = ov;
  1934.   for_all_vars (start_shift_var);
  1935.  
  1936.   /* This stack is used to defer adjustments to references that are entirely 
  1937.    * within FM.  Intra-FM references are adjusted after references into and
  1938.    * out of FM.
  1939.    */
  1940.  
  1941.   if (!moving)
  1942.     moving = init_stack ();
  1943.  
  1944.   find_cells_in_range (fm);
  1945.  
  1946.   while (cp = next_row_col_in_range (&rr, &cc))
  1947.     {
  1948.       /* cp/rr/cc is a cell in FM. */
  1949.  
  1950.       /* First, adjust references FROM the region */
  1951.       if (cp->cell_refs_to)
  1952.     {
  1953.       for (n = 0; n < cp->cell_refs_to->refs_used; n++)
  1954.         {
  1955.           fp = &(cp->cell_formula[cp->cell_refs_to->to_refs[n]]);
  1956.           switch (*fp)
  1957.         {
  1958.         case R_CELL:
  1959.         case R_CELL | ROWREL:
  1960.         case R_CELL | COLREL:
  1961.         case R_CELL | ROWREL | COLREL:
  1962.           /* Trr/cc/cp is the cell being referenced */
  1963.           trr = GET_ROW (fp + 1);
  1964.           tcc = GET_COL (fp + 1);
  1965.           tcp = find_cell (trr, tcc);
  1966.  
  1967.           /* Get rid of the backpointer to this reference. */
  1968.           flush_ref_fm (&(tcp->cell_refs_from), rr, cc);
  1969.  
  1970.           /* frr/fcc is the new address of the referenced cell.
  1971.            * The address will change if Trr/cc happens to be 
  1972.               * in the region that is moving, or if the reference
  1973.            * is a relative reference.
  1974.            */
  1975.           fn = (BETWEEN (trr, fm->lr, fm->hr)
  1976.             && BETWEEN (tcc, fm->lc, fm->hc)); 
  1977.           frr = (fn || (((*fp) & ROWREL))) ? trr + dn : trr;
  1978.           fcc = (fn || (((*fp) & COLREL))) ? tcc + ov : tcc;
  1979.  
  1980.           PUT_ROW (fp + 1, frr); /* Adjust the formula byte-code. */
  1981.           PUT_COL (fp + 1, fcc); /* This might even be a noop. */
  1982.  
  1983.           /* Reinstall the backreference, unless the new address of the
  1984.            * referenced cell is w/in the region being moved. (In which
  1985.            * case, defer making the backreference).
  1986.            */
  1987.           if (BETWEEN(frr, fm->lr, fm->hr) && BETWEEN(fcc, fm->lc, fm->hc))
  1988.             {
  1989.               push_stack (moving, (VOIDSTAR) TO_MAGIC (rr + dn, cc + ov));
  1990.               push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  1991.               push_stack (moving, DEF_REF);
  1992.             }
  1993.           else
  1994.             {
  1995.               tcp = find_or_make_cell (frr, fcc);
  1996.               add_ref_fm (&(tcp->cell_refs_from), rr + dn, cc + ov);
  1997.               cp = find_cell (rr, cc);
  1998.             }
  1999.  
  2000.           break;
  2001.  
  2002.         case VAR:
  2003.           {
  2004.             struct var * varp;
  2005.             bcopy ((VOIDSTAR) (fp + 1),
  2006.                (VOIDSTAR)&varp, sizeof (struct var *));
  2007.             flush_ref_fm (&varp->var_ref_fm, rr, cc);
  2008.             add_ref_fm (&varp->var_ref_fm, rr + dn, cc + ov);
  2009.             break;
  2010.           }
  2011.  
  2012.         case RANGE:
  2013.         case RANGE | LRREL:
  2014.         case RANGE | HRREL:
  2015.         case RANGE | LCREL:
  2016.         case RANGE | HCREL:
  2017.         case RANGE | LRREL | HRREL:
  2018.         case RANGE | LRREL | LCREL:
  2019.         case RANGE | LRREL | HCREL:
  2020.         case RANGE | HRREL | LCREL:
  2021.         case RANGE | HRREL | HCREL:
  2022.         case RANGE | LCREL | HCREL:
  2023.         case RANGE | LRREL | LCREL | HCREL:
  2024.         case RANGE | LRREL | HRREL | LCREL:
  2025.         case RANGE | LRREL | HRREL | HCREL:
  2026.         case RANGE | HRREL | LCREL | HCREL:
  2027.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  2028.           /* orng is the range being referenced. */
  2029.           GET_RNG (fp + 1, &orng);
  2030.  
  2031.           /* Get rid of backpointers to this reference. */
  2032.           flush_range_ref (&orng, rr, cc);
  2033.  
  2034.                   /* This asks -- does the referenced region
  2035.                       * intersect the region being moved at the: 
  2036.                    */
  2037.           fn = ((BETWEEN (orng.hc, fm->lc, fm->hc) << 3)   /* right?  8 */
  2038.                | (BETWEEN (orng.lc, fm->lc, fm->hc) << 2)  /* left?   4 */
  2039.                | (BETWEEN (orng.hr, fm->lr, fm->hr) << 1)  /* bottom? 2 */
  2040.                | BETWEEN (orng.lr, fm->lr, fm->hr));       /* top?    1 */
  2041.  
  2042.           /* In this switch, a union of masks represents a conjunction 
  2043.            * of intersections.  So, LEFT | TOP means `interects at left
  2044.            * and top'. 
  2045.            */
  2046.           switch (fn)
  2047.             {
  2048.               /* Most of the time, the referenced region is moved only
  2049.                * if the reference is relative.
  2050.                    */
  2051.             case LEFT | TOP:
  2052.             case LEFT | BOTTOM:
  2053.             case RIGHT | TOP:
  2054.             case RIGHT | BOTTOM:
  2055.  
  2056.               /* There used to be a warning given to the user here, but
  2057.                * that seems silly, no? 
  2058.                */
  2059.  
  2060.             case 0:
  2061.             case TOP:
  2062.             case BOTTOM:
  2063.             case TOP | BOTTOM:
  2064.             case LEFT:
  2065.             case RIGHT:
  2066.             case LEFT | RIGHT:
  2067.               if ((*fp) & LRREL)
  2068.             orng.lr += dn;
  2069.               if ((*fp) & HRREL)
  2070.             orng.hr += dn;
  2071.               if ((*fp) & LCREL)
  2072.             orng.lc += ov;
  2073.               if ((*fp) & HCREL)
  2074.             orng.hc += ov;
  2075.               break;
  2076.  
  2077.               /* If the referenced range contains rows or columns that
  2078.                * are entirely within the region being moved, then 
  2079.                * the region is moved, shrunk or stretched.
  2080.                */
  2081.             case LEFT | BOTTOM | TOP:
  2082.             case RIGHT | BOTTOM | TOP:
  2083.             case RIGHT | LEFT | TOP:
  2084.             case RIGHT | LEFT | BOTTOM:
  2085.             case RIGHT | LEFT | BOTTOM | TOP:
  2086.               if (fn != (LEFT | BOTTOM | TOP))
  2087.             orng.hc += ov;
  2088.               if (fn != (RIGHT | BOTTOM | TOP))
  2089.             orng.lc += ov;
  2090.               if (fn != (RIGHT | LEFT | TOP))
  2091.             orng.hr += dn;
  2092.               if (fn != (RIGHT | LEFT | BOTTOM))
  2093.             orng.lr += dn;
  2094.               break;
  2095.             }
  2096.           PUT_RNG (fp + 1, &orng); /* Patch the bytecode. */
  2097.  
  2098.           push_stack (moving, (VOIDSTAR) fp);
  2099.           push_stack (moving, (VOIDSTAR) TO_MAGIC (rr + dn, cc + ov));
  2100.           push_stack (moving, DEF_RNG);
  2101.           break;
  2102.  
  2103.         default:
  2104.           {
  2105.             struct function *fun;
  2106.  
  2107.             if (*fp < USR1)
  2108.               fun = &the_funs[*fp];
  2109.             else
  2110.               fun = &usr_funs[*fp - USR1][fp[1]];
  2111.  
  2112.             if (fun->fn_comptype & C_T)
  2113.               {
  2114.             flush_ref_fm (&timer_cells, rr, cc);
  2115.             add_ref_fm (&timer_cells, rr + dn, cc + ov);
  2116.               }
  2117.           }
  2118.           break;
  2119.         }
  2120.  
  2121.         }
  2122.     }
  2123.  
  2124.       /* Next, adjust references TO the region */
  2125.       for (n = 0; cp->cell_refs_from && n < cp->cell_refs_from->refs_used; n++)
  2126.     {
  2127.       /* The second enclosed loop over the bytecode will fix all of the
  2128.        * references to this cell.  This loop is here because a 
  2129.        * refs_fm structure may contain more than one occurence of the
  2130.        * referencing cell.  We don't want to adjust the same bytecode
  2131.        * twice.
  2132.        */
  2133.       while ((n < cp->cell_refs_from->refs_used - 1)
  2134.          && (cp->cell_refs_from->fm_refs[n].ref_row == 
  2135.              cp->cell_refs_from->fm_refs[n + 1].ref_row)
  2136.          && (cp->cell_refs_from->fm_refs[n].ref_col == 
  2137.              cp->cell_refs_from->fm_refs[n + 1].ref_col))
  2138.         ++n;
  2139.  
  2140.       /* For each cell that referenced this one, look
  2141.        * at the type of reference involved
  2142.        */
  2143.       frr = cp->cell_refs_from->fm_refs[n].ref_row;
  2144.       fcc = cp->cell_refs_from->fm_refs[n].ref_col;
  2145.  
  2146.       /* Unless the reference is from inside the region we're moving, in 
  2147.        * which case, it has already been adjusted.
  2148.        * 
  2149.        * (This test seems unnecessary but harmless. -tl)
  2150.        */
  2151.       if (BETWEEN (frr, fm->lr, fm->hr) && BETWEEN (fcc, fm->lc, fm->hc))
  2152.         continue;
  2153.  
  2154.       /* Find the cell that references cp. */
  2155.       fcp = find_cell (frr, fcc);
  2156.  
  2157.       /* Search the byte-code for the reference. */
  2158.       for (fn = 0; fcp->cell_refs_to && fn < fcp->cell_refs_to->refs_used; fn++)
  2159.         {
  2160.  
  2161.           ffp = &(fcp->cell_formula[fcp->cell_refs_to->to_refs[fn]]);
  2162.           switch (*ffp)
  2163.         {
  2164.         case R_CELL:
  2165.         case R_CELL | ROWREL:
  2166.         case R_CELL | COLREL:
  2167.         case R_CELL | ROWREL | COLREL:
  2168.  
  2169.           trr = GET_ROW (ffp + 1);
  2170.           tcc = GET_COL (ffp + 1);
  2171.  
  2172.           if (trr != rr || tcc != cc)
  2173.             continue;
  2174.  
  2175.           {
  2176.             CELLREF old_tr = trr;
  2177.             CELLREF old_tc = tcc;
  2178.             /* Find the cell that fcp should reference now. */
  2179.             if (!((*ffp) & ROWREL))
  2180.               {
  2181.             trr += dn;
  2182.             PUT_ROW (ffp + 1, trr);
  2183.               }
  2184.             if (!((*ffp) & COLREL))
  2185.               {
  2186.             tcc += ov;
  2187.             PUT_COL (ffp + 1, tcc);
  2188.               }
  2189.             else
  2190.               /* If this is an abs reference, it doesn't change. */
  2191.               continue;
  2192.             /* Get rid of the now-invalid backpointer */
  2193.             {
  2194.               CELL * old_reffed = find_cell (old_tr, old_tc);
  2195.               flush_ref_fm (&(old_reffed->cell_refs_from), frr, fcc);
  2196.             }
  2197.           }
  2198.  
  2199.           if (BETWEEN (trr, fm->lr, fm->hr) && BETWEEN (tcc, fm->lc, fm->hc))
  2200.             {
  2201.               push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  2202.               push_stack (moving, (VOIDSTAR) TO_MAGIC (trr, tcc));
  2203.               push_stack (moving, DEF_REF);
  2204.             }
  2205.           else
  2206.             {
  2207.               cp = find_or_make_cell (trr, tcc);
  2208.               add_ref_fm (&(cp->cell_refs_from), frr, fcc);
  2209.             }    
  2210.  
  2211.  
  2212.         case VAR:
  2213.           /* This case is taken care of by {start,finish}_shift_vars */
  2214.           continue;
  2215.  
  2216.         case RANGE:
  2217.         case RANGE | LRREL:
  2218.         case RANGE | LRREL | LCREL:
  2219.         case RANGE | LRREL | LCREL | HCREL:
  2220.         case RANGE | LRREL | HCREL:
  2221.         case RANGE | LRREL | HRREL:
  2222.         case RANGE | LRREL | HRREL | LCREL:
  2223.         case RANGE | LRREL | HRREL | LCREL | HCREL:
  2224.         case RANGE | LRREL | HRREL | HCREL:
  2225.         case RANGE | HRREL:
  2226.         case RANGE | HRREL | LCREL:
  2227.         case RANGE | HRREL | LCREL | HCREL:
  2228.         case RANGE | HRREL | HCREL:
  2229.         case RANGE | LCREL:
  2230.         case RANGE | LCREL | HCREL:
  2231.         case RANGE | HCREL:
  2232.           GET_RNG (ffp + 1, &orng);
  2233.  
  2234.           if (!BETWEEN (rr, orng.lr, orng.hr) || !BETWEEN (cc, orng.lc, orng.hc))
  2235.             break;
  2236.  
  2237.           val = ((BETWEEN (orng.hc, fm->lc, fm->hc) << 3) /* right */
  2238.              + (BETWEEN (orng.lc, fm->lc, fm->hc) << 2) /* left */
  2239.              + (BETWEEN (orng.hr, fm->lr, fm->hr) << 1) /* bottom */
  2240.              + BETWEEN (orng.lr, fm->lr, fm->hr)); /* top */
  2241.  
  2242.           /* If the reference is absolute, or relative only in directions
  2243.            * that aren't changing, there's nothing to do. 
  2244.            */
  2245.           if (!(*ffp == RANGE
  2246.             || (!dn && ((*ffp) | LRREL | HRREL) == (RANGE | LRREL | HRREL))
  2247.             || (!ov && ((*ffp) | LCREL | HCREL) == (RANGE | LCREL | HCREL))))
  2248.             continue;
  2249.  
  2250.           /* If it's a case we don't know how to adjust, there's
  2251.            * nothing to do.  If there is no overlap, there's nothing to
  2252.            * do.
  2253.            */
  2254.           if ((val != (LEFT | BOTTOM | TOP))
  2255.               && (val != (RIGHT | BOTTOM | TOP))
  2256.               && (val != (RIGHT | LEFT | TOP))
  2257.               && (val != (RIGHT | LEFT | BOTTOM))
  2258.               && (val != (RIGHT | LEFT | BOTTOM | TOP)))
  2259.             continue;
  2260.           
  2261.           flush_range_ref (&orng, frr, fcc);
  2262.  
  2263.           if (val != (RIGHT | LEFT | BOTTOM))
  2264.             orng.lr += dn;
  2265.           if (val != (RIGHT | LEFT | TOP))
  2266.             orng.hr += dn;
  2267.           if (val != (RIGHT | BOTTOM | TOP))
  2268.             orng.lc += ov;
  2269.           if (val != (LEFT | BOTTOM  | TOP))
  2270.             orng.hc += ov;
  2271.           PUT_RNG (ffp + 1, &orng);
  2272.           push_stack (moving, (VOIDSTAR) ffp);
  2273.           push_stack (moving, (VOIDSTAR) TO_MAGIC (frr, fcc));
  2274.           push_stack (moving, DEF_RNG);
  2275.           continue;
  2276. #ifdef TEST
  2277.         default:
  2278.           { struct function *fun; if (*ffp < USR1) fun =
  2279.               &the_funs[*ffp]; else if (*ffp >= SKIP) fun = 0, panic
  2280.             ("SKIP? in shift_outside()"); else fun =
  2281.               &usr_funs[*ffp][ffp[1]];
  2282.             if ((fun->fn_comptype & C_T) == 0) io_error_msg
  2283.               ("Unknown byte (%d) for reference_to #%d %d",
  2284.                *ffp, fn, fcp->cell_refs_to->to_refs[fn]);
  2285.           }
  2286.           break; 
  2287. #endif
  2288.         }
  2289.         }
  2290.     }
  2291.     }
  2292.  
  2293.   while (ptr = pop_stack (moving))
  2294.     {
  2295.       if (ptr == DEF_REF)
  2296.     {
  2297.       val = (unsigned long) pop_stack (moving);
  2298.       trr = MAGIC_ROW (val);
  2299.       tcc = MAGIC_COL (val);
  2300.       val = (unsigned long) pop_stack (moving);
  2301.       cp = find_or_make_cell (trr, tcc);
  2302.       add_ref_fm (&(cp->cell_refs_from), MAGIC_ROW (val), MAGIC_COL (val));
  2303.     }
  2304.       else if (ptr == DEF_RNG)
  2305.     {
  2306.       val = (unsigned long) pop_stack (moving);
  2307.       cur_row = MAGIC_ROW (val);
  2308.       cur_col = MAGIC_COL (val);
  2309.       ffp = (unsigned char *) pop_stack (moving);
  2310.  
  2311.       GET_RNG (ffp + 1, &orng);
  2312.       add_range_ref (&orng);
  2313.       if (my_cell)
  2314.         panic ("shift_outside: my_cell lost.");
  2315.       /* If this panic occurs, the caller should be recomputing
  2316.        * my_cell after shift_outside returns (and this useful panic
  2317.        * will have to be removed or my_cell set temporarily to 0).
  2318.        */
  2319.     }
  2320. #ifdef TEST
  2321.       else
  2322.     panic ("Now what (%p)?", ptr);
  2323. #endif
  2324.     }
  2325.   for_all_vars (finish_shift_var);
  2326.   /* flush_stack(moving); */
  2327. }
  2328.  
  2329. /* The formula in cell my_cell has moved by DN down and OV over, adjust
  2330.    everything so it'll still work */
  2331. #ifdef __STDC__
  2332. void
  2333. shift_formula (int r, int c, int dn, int ov)
  2334. #else
  2335. void
  2336. shift_formula (r, c, dn, ov)
  2337.      int r;            /* Address of my_cell. */
  2338.      int c;
  2339.      int dn;
  2340.      int ov;
  2341. #endif
  2342. {
  2343.   int n;
  2344.   unsigned char *fp;
  2345.  
  2346.   for (n = 0; n < my_cell->cell_refs_to->refs_used; n++)
  2347.     {
  2348.       fp = &(my_cell->cell_formula[my_cell->cell_refs_to->to_refs[n]]);
  2349.       switch (*fp)
  2350.     {
  2351.     case F_ROW:
  2352.     case F_COL:
  2353.       push_cell (cur_row, cur_col);
  2354.       break;
  2355.  
  2356.     case R_CELL:
  2357.     case R_CELL | ROWREL:
  2358.     case R_CELL | COLREL:
  2359.     case R_CELL | ROWREL | COLREL:
  2360.       {
  2361.         CELLREF trr, tcc;
  2362.         CELL *tcp;
  2363.  
  2364.         /* These are more difficult */
  2365.         trr = GET_ROW (fp + 1);
  2366.         tcc = GET_COL (fp + 1);
  2367.         tcp = find_cell (trr, tcc);
  2368. #ifdef TEST
  2369.         if (!tcp)
  2370.           panic ("Can't find_cell(%s) in shift_formula", cell_name (trr, tcc));
  2371. #endif
  2372.         flush_ref_fm (&(tcp->cell_refs_from), cur_row - dn, cur_col - ov);
  2373.  
  2374.         if (((*fp) & ROWREL) && dn)
  2375.           {
  2376.         trr += dn;
  2377.         PUT_ROW (fp + 1, trr);
  2378.           }
  2379.         if (((*fp) & COLREL) && ov)
  2380.           {
  2381.         tcc += ov;
  2382.         PUT_COL (fp + 1, tcc);
  2383.           }
  2384.         tcp = find_or_make_cell (trr, tcc);
  2385.         add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  2386.       }
  2387.       break;
  2388.  
  2389.     case RANGE:
  2390.     case RANGE | LRREL:
  2391.     case RANGE | LRREL | LCREL:
  2392.     case RANGE | LRREL | LCREL | HCREL:
  2393.     case RANGE | LRREL | HCREL:
  2394.     case RANGE | LRREL | HRREL:
  2395.     case RANGE | LRREL | HRREL | LCREL:
  2396.     case RANGE | LRREL | HRREL | LCREL | HCREL:
  2397.     case RANGE | LRREL | HRREL | HCREL:
  2398.     case RANGE | HRREL:
  2399.     case RANGE | HRREL | LCREL:
  2400.     case RANGE | HRREL | LCREL | HCREL:
  2401.     case RANGE | HRREL | HCREL:
  2402.     case RANGE | LCREL:
  2403.     case RANGE | LCREL | HCREL:
  2404.     case RANGE | HCREL:
  2405.       {
  2406.         struct rng orng;
  2407.         GET_RNG (fp + 1, &orng);
  2408.  
  2409.         flush_range_ref (&orng, cur_row - dn, cur_col - ov);
  2410.  
  2411.         if ((*fp) & LRREL)
  2412.           orng.lr += dn;
  2413.         if ((*fp) & HRREL)
  2414.           orng.hr += dn;
  2415.         if ((*fp) & LCREL)
  2416.           orng.lc += ov;
  2417.         if ((*fp) & HCREL)
  2418.           orng.hc += ov;
  2419.         PUT_RNG (fp + 1, &orng);
  2420.         add_range_ref (&orng);
  2421.         /* sparse array bug fixed here */
  2422.         my_cell = find_cell (r, c);
  2423.       }
  2424.       break;
  2425.  
  2426.     case VAR:
  2427.       {
  2428.         struct var *v;
  2429.         struct cell *tcp;
  2430.  
  2431.         bcopy (&fp[1], &v, sizeof (struct var *));
  2432.         flush_ref_fm (&(v->var_ref_fm), cur_row - dn, cur_col - ov);
  2433.         add_ref_fm (&(v->var_ref_fm), cur_row, cur_col);
  2434.         switch (v->var_flags)
  2435.           {
  2436.           case VAR_UNDEF:
  2437.         break;
  2438.  
  2439.           case VAR_CELL:
  2440.         tcp = find_cell (v->v_rng.lr, v->v_rng.lc);
  2441. #ifdef TEST
  2442.         if (!tcp)
  2443.           panic ("Can't find_cell(%s) in shift_formula", cell_name (v->v_rng.lr, v->v_rng.lc));
  2444. #endif
  2445.         flush_ref_fm (&(tcp->cell_refs_from), cur_row - dn, cur_col - ov);
  2446.         add_ref_fm (&(tcp->cell_refs_from), cur_row, cur_col);
  2447.         break;
  2448.  
  2449.           case VAR_RANGE:
  2450.         flush_range_ref (&(v->v_rng), cur_row - dn, cur_col - ov);
  2451.         add_range_ref (&(v->v_rng));
  2452.         /* sparse array bug fixed here */
  2453.         my_cell = find_cell (r, c);
  2454.         break;
  2455.  
  2456. #ifdef TEST
  2457.           default:
  2458.         panic ("Unknown var type %d", v->var_flags);
  2459. #endif
  2460.           }
  2461.       }
  2462.       break;
  2463.  
  2464.     default:
  2465.       {
  2466.         struct function *fun;
  2467.  
  2468.         if (*fp < USR1)
  2469.           fun = &the_funs[*fp];
  2470. #ifdef TEST
  2471.         else if (*fp >= SKIP)
  2472.           fun = 0, panic ("SKIP? in shift_formula?");
  2473. #endif
  2474.         else
  2475.           fun = &usr_funs[*fp][fp[1]];
  2476.         /* These are easy */
  2477.         if (fun->fn_comptype & C_T)
  2478.           {
  2479.         flush_ref_fm (&timer_cells, cur_row - dn, cur_col - ov);
  2480.         add_ref_fm (&timer_cells, cur_row, cur_col);
  2481.           }
  2482. #ifdef TEST
  2483.         else
  2484.           panic ("How do I deal with byte %d in shift_formula()?", *fp);
  2485. #endif
  2486.       }
  2487.       break;
  2488.     }
  2489.     }
  2490. }
  2491.  
  2492.  
  2493. /* ---------------- Routines for dealing with async functions -------------- */
  2494.  
  2495.  
  2496. /* This function is called when the alarm has gone off (but not from inside
  2497.  * the signal handler!). It schedules timer_cells->fm_refs for recalc. 
  2498.  */
  2499. #ifdef __STDC__
  2500. void
  2501. cell_alarm (void)
  2502. #else
  2503. void
  2504. cell_alarm ()
  2505. #endif
  2506. {
  2507.   int n;
  2508.   static time_t last_time = 0;
  2509.   if (timer_active)
  2510.     {
  2511.       time_t this_time = time(0);
  2512.       if ((this_time - last_time) < cell_timer_seconds)
  2513.     return;
  2514.       last_time = this_time;
  2515.       current_cycle++;
  2516.       for (n = 0; n < timer_cells->refs_used; n++)
  2517.     push_cell (timer_cells->fm_refs[n].ref_row,
  2518.            timer_cells->fm_refs[n].ref_col);
  2519.     }
  2520. }
  2521.  
  2522. /* All the timer_cells are going away, 'cuz everything is going away. . . */
  2523. #ifdef __STDC__
  2524. void
  2525. flush_all_timers (void)
  2526. #else
  2527. void
  2528. flush_all_timers ()
  2529. #endif
  2530. {
  2531.   if (timer_active)
  2532.     {
  2533. #ifdef SPLIT_REFS
  2534.       timer_cells->refs_used = 0;
  2535. #else
  2536.       flush_fm_ref (timer_cells);
  2537.       timer_cells = 0;
  2538. #endif
  2539.       timer_active = 0;
  2540.     }
  2541. }
  2542.  
  2543. /* Add CUR_ROW, CUR_COL to the list of active timer-cells, turning on
  2544.    the timer_active, if it isn't already */
  2545. #ifdef __STDC__
  2546. void
  2547. add_timer_ref (int whereto)
  2548. #else
  2549. void
  2550. add_timer_ref (whereto)
  2551.      int whereto;
  2552. #endif
  2553. {
  2554.   add_ref_to (whereto);
  2555.   add_ref_fm (&timer_cells, cur_row, cur_col);
  2556.   ++timer_active;
  2557. }
  2558.  
  2559. /* ---------- Routines and vars for dealing with the eval FIFO ------------ */
  2560. static struct cell_buf cell_buffer;
  2561.  
  2562. /* Start up the FIFO of cells to update */
  2563. #ifdef __STDC__
  2564. void
  2565. init_refs (void)
  2566. #else
  2567. void
  2568. init_refs ()
  2569. #endif
  2570. {
  2571.   cell_buffer.size = FIFO_START;
  2572.   cell_buffer.buf = (struct pos *) ck_malloc (cell_buffer.size * sizeof (struct pos));
  2573.   bzero (cell_buffer.buf, cell_buffer.size * sizeof (struct pos));
  2574.   cell_buffer.push_to_here = cell_buffer.buf;
  2575.   cell_buffer.pop_frm_here = cell_buffer.buf;
  2576.   the_vars = hash_new ();
  2577. }
  2578.  
  2579. /* Push the cells in REF onto the FIFO.  This calls push_cell to do the
  2580.    actual work. . . */
  2581. #ifdef __STDC__
  2582. void
  2583. push_refs (struct ref_fm *ref)
  2584. #else
  2585. void
  2586. push_refs (ref)
  2587.      struct ref_fm *ref;
  2588. #endif
  2589. {
  2590.   int n;
  2591.  
  2592.   if (!ref || !ref->refs_used)
  2593.     return;
  2594.   n = ref->refs_used;
  2595.   while (n--)
  2596.     {
  2597. #ifdef TEST
  2598.       CELL *cp;
  2599.  
  2600.       if (debug & 04)
  2601.     io_error_msg ("Push %s", cell_name (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col));
  2602.       cp = find_cell (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col);
  2603.       if (cp->cell_cycle == current_cycle)
  2604.     {
  2605.       if (debug & 01)
  2606.         io_error_msg ("Cycle detected from %s to %s",
  2607.               cell_name (cur_row, cur_col),
  2608.           cell_name (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col));
  2609.       push_cell (ref->fm_refs[n].ref_row,
  2610.              ref->fm_refs[n].ref_col);
  2611.     }
  2612.       else
  2613. #endif
  2614.     push_cell (ref->fm_refs[n].ref_row, ref->fm_refs[n].ref_col);
  2615.     }
  2616. }
  2617.  
  2618. /* Push a cell onto the FIFO of cells to evaluate, checking for cells
  2619.    that are already on the FIFO, etc.
  2620.  
  2621.    This does not implement best-order recalculation, since there may be
  2622.    intersecting branches in the dependency tree, however, it's close enough
  2623.    for most people.
  2624.  */
  2625. #ifdef __STDC__
  2626. void
  2627. push_cell (CELLREF row, CELLREF col)
  2628. #else
  2629. void
  2630. push_cell (row, col)
  2631.      CELLREF row;
  2632.      CELLREF col;
  2633. #endif
  2634. {
  2635.   struct pos *dup;
  2636.   CELL *cp;
  2637.   struct ref_fm *rf;
  2638.  
  2639.   if (cell_buffer.push_to_here + 1 == cell_buffer.pop_frm_here || (cell_buffer.pop_frm_here == cell_buffer.buf && cell_buffer.push_to_here == cell_buffer.buf + (cell_buffer.size - 1)))
  2640.     {
  2641.       int f, t, from_num;
  2642.  
  2643.       f = cell_buffer.pop_frm_here - cell_buffer.buf;
  2644.       t = cell_buffer.push_to_here - cell_buffer.buf;
  2645.       from_num = cell_buffer.size - f;
  2646.  
  2647.       cell_buffer.size FIFO_INC;
  2648.       cell_buffer.buf = (struct pos *) ck_realloc ((VOIDSTAR) cell_buffer.buf, cell_buffer.size * sizeof (struct pos));
  2649.       if (t == 0)
  2650.     {
  2651.       cell_buffer.push_to_here = cell_buffer.buf + f + from_num;
  2652.       cell_buffer.pop_frm_here = cell_buffer.buf + f;
  2653.     }
  2654.       else if (t > f)
  2655.     {
  2656.       cell_buffer.push_to_here = cell_buffer.buf + t;
  2657.       cell_buffer.pop_frm_here = cell_buffer.buf + f;
  2658.     }
  2659.       else
  2660.     {
  2661.       cell_buffer.push_to_here = cell_buffer.buf + t;
  2662.       cell_buffer.pop_frm_here = cell_buffer.buf + (cell_buffer.size - from_num);
  2663.       if (from_num)
  2664.         bcopy (cell_buffer.buf + f,
  2665.            cell_buffer.pop_frm_here,
  2666.            from_num * sizeof (struct pos));
  2667.     }
  2668.     }
  2669.  
  2670. #if 1
  2671.   if (cell_buffer.pop_frm_here != cell_buffer.push_to_here)
  2672.     {
  2673.       dup = cell_buffer.pop_frm_here;
  2674.  
  2675.       cp = find_cell (row, col);
  2676.       if (!cp)
  2677.     {
  2678.       return;
  2679.     }
  2680.       rf = cp->cell_refs_from;
  2681.       for (; dup != cell_buffer.push_to_here;)
  2682.     {
  2683.       if (dup->row == row && dup->col == col)
  2684.         {
  2685. #ifdef TEST
  2686.           if (debug & 010)
  2687.         io_error_msg ("Flushed dup ref to %s", cell_name (row, col));
  2688. #endif
  2689.           *dup = *(cell_buffer.pop_frm_here);
  2690.           cell_buffer.pop_frm_here++;
  2691.           if (cell_buffer.pop_frm_here == cell_buffer.buf + cell_buffer.size)
  2692.         cell_buffer.pop_frm_here = cell_buffer.buf;
  2693.           break;
  2694.         }
  2695. #if 0
  2696.       if (rf)
  2697.         {
  2698.           for (n = 0; n < rf->refs_used; n++)
  2699.         if (rf->fm_refs[n].ref_row == dup->row && rf->fm_refs[n].ref_col == dup->col)
  2700.           {
  2701. #ifdef TEST
  2702.             if (debug & 01)
  2703.               io_error_msg ("Swapped %s and %s", cell_name (row, col), cell_name (dup->row, dup->col));
  2704. #endif
  2705.             dup->row = row;
  2706.             dup->col = col;
  2707.             row = rf->fm_refs[n].ref_row;
  2708.             col - rf->fm_refs[n].ref_col;
  2709.             goto breakout;
  2710.           }
  2711.         }
  2712. #endif
  2713.  
  2714.       if (++dup == cell_buffer.buf + cell_buffer.size)
  2715.         dup = cell_buffer.buf;
  2716.     }
  2717.     }
  2718. #endif
  2719.  
  2720.   cell_buffer.push_to_here->row = row;
  2721.   cell_buffer.push_to_here->col = col;
  2722.   cell_buffer.push_to_here++;
  2723.   if (cell_buffer.push_to_here == cell_buffer.buf + cell_buffer.size)
  2724.     cell_buffer.push_to_here = cell_buffer.buf;
  2725. }
  2726.  
  2727. /* Pop a cell off CELL_BUFFER, and evaluate it, displaying the result. . .
  2728.    This returns 0 if there are no more cells to update, or if it gets
  2729.    an error. */
  2730.  
  2731. #ifdef __STDC__
  2732. int
  2733. eval_next_cell (void)
  2734. #else
  2735. int
  2736. eval_next_cell ()
  2737. #endif
  2738. {
  2739.   CELL *cp;
  2740.   static loop_counter = 40;
  2741.  
  2742.   if (cell_buffer.pop_frm_here == cell_buffer.push_to_here)
  2743.     return 0;
  2744.  
  2745.   cur_row = cell_buffer.pop_frm_here->row;
  2746.   cur_col = cell_buffer.pop_frm_here->col;
  2747.   cell_buffer.pop_frm_here++;
  2748.   if (cell_buffer.pop_frm_here == cell_buffer.buf + cell_buffer.size)
  2749.     cell_buffer.pop_frm_here = cell_buffer.buf;
  2750.  
  2751.   cp = find_cell (cur_row, cur_col);
  2752.   if (cp)
  2753.     {
  2754.       if (cp->cell_cycle == current_cycle)
  2755.     --loop_counter;
  2756.       else
  2757.     loop_counter = 40;
  2758.       update_cell (cp);
  2759.       io_pr_cell (cur_row, cur_col, cp);
  2760.       return loop_counter;
  2761.     }
  2762.   else
  2763.     return 0;
  2764. }
  2765.  
  2766. #ifdef TEST
  2767. void
  2768. cell_buffer_contents ()
  2769. {
  2770.   struct pos *ptr;
  2771.  
  2772.   if (cell_buffer.pop_frm_here != cell_buffer.push_to_here)
  2773.     {
  2774.       ptr = cell_buffer.pop_frm_here;
  2775.       for (;;)
  2776.     {
  2777.       printf ("Ref to %s\r\n", cell_name (ptr->row, ptr->col));
  2778.       if (++ptr == cell_buffer.buf + cell_buffer.size)
  2779.         ptr = cell_buffer.buf;
  2780.       if (ptr == cell_buffer.push_to_here)
  2781.         break;
  2782.     }
  2783.     }
  2784.   printf ("End of buffer\r\n");
  2785. }
  2786.  
  2787. #endif
  2788.  
  2789. /* ----------------- Routines for dealing with variables ------------------ */
  2790.  
  2791. /* This sets the variable V_NAME to V_NEWVAL
  2792.    It returns error msg, or 0 on success.
  2793.    All the appropriate cells have their ref_fm arrays adjusted appropriatly
  2794.    This could be smarter; when changing a range var, only the cells that
  2795.    were in the old value but not in the new one need their references flushed,
  2796.    and only the cells that are new need references added.
  2797.    This might also be changed to use add_range_ref()?
  2798.  */
  2799. #ifdef __STDC__
  2800. char *
  2801. new_var_value (char *v_name, int v_namelen, char *v_newval)
  2802. #else
  2803. char *
  2804. new_var_value (v_name, v_namelen, v_newval)
  2805.      char *v_name;
  2806.      int v_namelen;
  2807.      char *v_newval;
  2808. #endif
  2809. {
  2810.   struct var *var;
  2811.   int n;
  2812.   int newflag;
  2813.   struct rng tmp_rng;
  2814.  
  2815.   cur_row = MIN_ROW;
  2816.   cur_col = MIN_COL;
  2817.   if (v_newval && *v_newval)
  2818.     {
  2819.       n = parse_cell_or_range (&v_newval, &tmp_rng);
  2820.       if (!n)
  2821.     return "Can't parse cell or range";
  2822.       if (*v_newval)
  2823.     return "Junk after cell or range";
  2824.       newflag = ((n | ROWREL | COLREL) == (R_CELL | ROWREL | COLREL)) ? VAR_CELL : VAR_RANGE;
  2825.     }
  2826.   else
  2827.     {
  2828.       tmp_rng.lr = tmp_rng.hr = NON_ROW;
  2829.       tmp_rng.lc = tmp_rng.hc = NON_COL;
  2830.       newflag = VAR_UNDEF;
  2831.     }
  2832.  
  2833.   var = find_or_make_var (v_name, v_namelen);
  2834.  
  2835.   if (var->var_ref_fm)
  2836.     {
  2837.       if (var->var_flags != VAR_UNDEF)
  2838.     {
  2839.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2840.         {
  2841.           flush_range_ref (&(var->v_rng),
  2842.                    var->var_ref_fm->fm_refs[n].ref_row,
  2843.                    var->var_ref_fm->fm_refs[n].ref_col);
  2844.         }
  2845.     }
  2846.       var->v_rng = tmp_rng;
  2847.  
  2848.       if (var->v_rng.lr != NON_ROW)
  2849.     {
  2850.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2851.         {
  2852.           cur_row = var->var_ref_fm->fm_refs[n].ref_row;
  2853.           cur_col = var->var_ref_fm->fm_refs[n].ref_col;
  2854.           add_range_ref (&(var->v_rng));
  2855.         }
  2856.     }
  2857.       for (n = 0; n < var->var_ref_fm->refs_used; n++)
  2858.     push_cell (var->var_ref_fm->fm_refs[n].ref_row,
  2859.            var->var_ref_fm->fm_refs[n].ref_col);
  2860.     }
  2861.   else
  2862.     var->v_rng = tmp_rng;
  2863.  
  2864.   var->var_flags = newflag;
  2865.  
  2866.   return 0;
  2867. }
  2868.  
  2869. #ifdef __STDC__
  2870. void
  2871. for_all_vars (void (*func) (char *, struct var *))
  2872. #else
  2873. void
  2874. for_all_vars (func)
  2875.      void (*func) ();
  2876. #endif
  2877. {
  2878.   hash_apply (the_vars, func);
  2879. }
  2880.  
  2881. /* Find a variable in the list of variables, or create it if it doesn't
  2882.    exist.  Takes a name and a length so the name doesn't have to be
  2883.    null-terminated
  2884.  */
  2885. #ifdef __STDC__
  2886. struct var *
  2887. find_or_make_var (char *string, int len)
  2888. #else
  2889. struct var *
  2890. find_or_make_var (string, len)
  2891.      char *string;
  2892.      int len;
  2893. #endif
  2894. {
  2895.   struct var *ret;
  2896.   int ch;
  2897.  
  2898.   ch = string[len];
  2899.   string[len] = '\0';
  2900.  
  2901.   ret = (struct var *) hash_find (the_vars, string);
  2902.   if (ret)
  2903.     {
  2904.       string[len] = ch;
  2905.       return ret;
  2906.     }
  2907.  
  2908.   ret = (struct var *) ck_malloc (sizeof (struct var) + len);
  2909.   bcopy (string, ret->var_name, len + 1);
  2910.   ret->var_flags = VAR_UNDEF;
  2911.   ret->v_rng.lr = 0;
  2912.   ret->v_rng.lc = 0;
  2913.   ret->v_rng.hr = 0;
  2914.   ret->v_rng.hc = 0;
  2915.   ret->var_ref_fm = 0;
  2916.   hash_insert (the_vars, ret->var_name, ret);
  2917.   string[len] = ch;
  2918.   return ret;
  2919. }
  2920.  
  2921. /* Like find-or-make-var except returns 0 if it doesn't exist */
  2922. #ifdef __STDC__
  2923. struct var *
  2924. find_var (char *string, int len)
  2925. #else
  2926. struct var *
  2927. find_var (string, len)
  2928.      char *string;
  2929.      int len;
  2930. #endif
  2931. {
  2932.   int ch;
  2933.   struct var *ret;
  2934.  
  2935.   ch = string[len];
  2936.   string[len] = '\0';
  2937.   ret = (struct var *) hash_find (the_vars, string);
  2938.   string[len] = ch;
  2939.   return ret;
  2940. }
  2941.  
  2942. /* This adds a reference from CUR_ROW,CUR_COL to the variable VAR
  2943.    It calls add_ref or add_range_ref to have the cell(s) in VAR be
  2944.    referenced by CUR_ROW,CUR_COL
  2945.  */
  2946. #ifdef __STDC__
  2947. void
  2948. add_var_ref (void * vvar)
  2949. #else
  2950. void
  2951. add_var_ref (vvar)
  2952.      void * vvar;
  2953. #endif
  2954. {
  2955.   struct var *var = (struct var *)vvar;
  2956.   add_ref_fm (&(var->var_ref_fm), cur_row, cur_col);
  2957.   switch (var->var_flags)
  2958.     {
  2959.     case VAR_UNDEF:
  2960.       break;
  2961.     case VAR_CELL:
  2962.       add_ref (var->v_rng.lr, var->v_rng.lc);
  2963.       break;
  2964.     case VAR_RANGE:
  2965.       add_range_ref (&(var->v_rng));
  2966.       break;
  2967. #ifdef TEST
  2968.     default:
  2969.       panic ("Unknown var type %d in add_var_ref", var->var_flags);
  2970. #endif
  2971.     }
  2972. }
  2973.  
  2974. #ifdef __STDC__
  2975. static void
  2976. flush_var (char *name, struct var *var)
  2977. #else
  2978. static void
  2979. flush_var (name, var)
  2980.      char *name;
  2981.      struct var *var;
  2982. #endif
  2983. {
  2984. #ifdef SPLIT_REFS
  2985.   if (var->var_ref_fm)
  2986.     free (var->var_ref_fm);
  2987. #endif
  2988.   free (var);
  2989. }
  2990.  
  2991.  
  2992. /* Free up all the variables, and (if SPLIT_REFS) the ref_fm structure
  2993.    associated with each variable.  Note that this does not get rid of
  2994.    the struct var *s in cell expressions, so it can only be used when all
  2995.    the cells are being freed also
  2996.  */
  2997. #ifdef __STDC__
  2998. void
  2999. flush_variables (void)
  3000. #else
  3001. void
  3002. flush_variables ()
  3003. #endif
  3004. {
  3005.   for_all_vars (flush_var);
  3006.   hash_die (the_vars);
  3007.   the_vars = hash_new ();
  3008. }
  3009.